some well known stupidness in c99

E

Eric Sosman

[...]
For example as to

char* main(char* arg)
{
return "hallo world";
}

(or close to that couse there can be unresolved details here)

some people just said that no oses are
ready for that - but it is not important
here becousa I am talking about 'technical goodness' here

To me, "technical goodness" has "it works" as a prerequisite.
If it doesn't work, it can't be technically good. I'm just not
interested in elegant failures.
 
E

Eric Sosman

[...]
Well, new functionality, including labels that aren't resolved at
compile time and that don't have to be distinct should probably come
with a new and differently named statement.

How about select/case that takes the first among the choices, and where
values can be determined at run time?

Like if/else if/else if/.../else?
 
B

BartC

Eric Sosman said:
[...]
Well, new functionality, including labels that aren't resolved at
compile time and that don't have to be distinct should probably come
with a new and differently named statement.

How about select/case that takes the first among the choices, and where
values can be determined at run time?

Like if/else if/else if/.../else?

Yes. Except it's written as:

switch(x) { case a: ... case b: ... case c: ... default: ...}

(with perhaps a new keyword as suggested) instead of:

if (x==a) ... else if (x==b) ... else if (x==c) ... else ...

with the same advantages that a, b, etc can be run-time expressions of any
type, but without the disadvantage that x is can be evaluated more then
once).
 
F

fir

W dniu środa, 21 listopada 2012 01:00:37 UTC+1 użytkownik fir napisał:
char* main(char* arg)
{
return "hallo world";
}

I could also add (as to this all) that sometimes
some difficulties make me really sad, for example this above looks really god for me, but
this (when this syntax passes also sizes in the background)

char[] main(char[] arg)
{
return "hallo world";
}

looks worse, maybe something like

char *$ main(char *$ arg)
{
return "hallo world";
}

where *$ means 'adress and size pair' would be better? maybe $a instead of lengthof(a) would be better - it is difficult not to fail aesteheticaly here and it is sad - takes whole years to clarify
 
G

glen herrmannsfeldt

Eric Sosman said:
On 11/21/2012 1:30 PM, glen herrmannsfeldt wrote:
Like if/else if/else if/.../else?

Yes, but in a more structured form.

As Fortran I showed, you can do everything with IF and GOTO, but it
is much nicer to program with more structured languages.

Why not a structured form, like switch, for the case where the choices
aren't known until run time? Much more readable than the if/else if/else
series. (Most likely the generated code is in if/else form.)

-- glen
 
B

BartC

glen herrmannsfeldt said:
Yes, but in a more structured form.

As Fortran I showed, you can do everything with IF and GOTO, but it
is much nicer to program with more structured languages.

Why not a structured form, like switch, for the case where the choices
aren't known until run time? Much more readable than the if/else if/else
series. (Most likely the generated code is in if/else form.)

Does any recent Fortran (or any language for that matter) actually have such
a statement?

(BTW we are in 2012 now you know, with all this talk of Fortran I and OS
360. I think they were already obsolete when I started programming 35 years
ago...)

In my own language projects, obviously I will have these two kinds of
statements, plus various variations I won't bore you with.

But I have found that people don't seem like useful extra syntax in their
favourite languages. Or perhaps more accurately, if their favourite language
doesn't have a particularly handy construction, they will defend the lack
of it to the death!

So, we don't need an if-else version of switch, because we can just use
if-else, and the compiler will end up generating the same code anyway. But
like you say, there would never be a reason to progress beyond if-then-goto
in that case.
 
I

Ian Collins

fir said:
I could also add (as to this all) that sometimes some difficulties
make me really sad, for example this above looks really god for me,
but this (when this syntax passes also sizes in the background)

char[] main(char[] arg) { return "hallo world"; }

looks worse, maybe something like

char *$ main(char *$ arg) { return "hallo world"; }

where *$ means 'adress and size pair' would be better? maybe $a
instead of lengthof(a) would be better - it is difficult not to
fail aesteheticaly here and it is sad - takes whole years to
clarify

I wish I could aspire to this level of comedy.

Aspire away, achievement may be more of a problem!
 
G

glen herrmannsfeldt

(snip, someone wrote)
(snip, then I wrote)
Does any recent Fortran (or any language for that matter) actually have such
a statement?

Verilog has the run-time value switch/case:

http://eesun.free.fr/DOC/VERILOG/verilog_manual1.html#7.2

Otherwise, Fortran, I believe since Fortran 90, has SELECT/CASE with
the usual compile-time constants and unique CASE values. (Fortran
CASE allows for a start:end range in addition to single values,
with either start or end, but not both at the same time, optional.)
(BTW we are in 2012 now you know, with all this talk of Fortran I and OS
360. I think they were already obsolete when I started programming 35 years
ago...)

Sorry about that.
In my own language projects, obviously I will have these two kinds of
statements, plus various variations I won't bore you with.
But I have found that people don't seem like useful extra syntax in their
favourite languages. Or perhaps more accurately, if their favourite language
doesn't have a particularly handy construction, they will defend the lack
of it to the death!

It does take time to get used to change. In the days before Fortran 77
there were various preprocessors to generate standard Fortran from a
new, structured language. RATFOR and MORTRAN are two that I know about.

But they never got as popular as you might think, give the advantages
of structured programming.
So, we don't need an if-else version of switch, because we can just use
if-else, and the compiler will end up generating the same code anyway.
But like you say, there would never be a reason to progress
beyond if-then-goto in that case.

If it isn't needed all that often, maybe it isn't worth adding.

There is cost in the complexity of compilers, and the ability of people
to remember how to use new features. But people can always use just
their favorite subset when writing their own programs. You have to at
least have a good reference when reading programs written by others.

If I didn't have one, and had a program that needed it, I might write
a special use preprocessor to generate the if/elseif/else chain.

Another possibity is to code the logic to convert the values, possibly
through a loop and look-up table, to constants. Slower, but it might
work well enough.

-- glen
 
F

fir

W dniu środa, 21 listopada 2012 22:49:25 UTC+1 użytkownik Ian Collins napisał:
I could also add (as to this all) that sometimes some difficulties
make me really sad, for example this above looks really god for me,
but this (when this syntax passes also sizes in the background)

char[] main(char[] arg) { return "hallo world"; }

looks worse, maybe something like

char *$ main(char *$ arg) { return "hallo world"; }

where *$ means 'adress and size pair' would be better? maybe $a
instead of lengthof(a) would be better - it is difficult not to
fail aesteheticaly here and it is sad - takes whole years to
clarify
I wish I could aspire to this level of comedy.



Aspire away, achievement may be more of a problem!

ależ błyskotliwe! (ziew po polsku)
 
B

Ben Bacarisse

BartC said:
Does any recent Fortran (or any language for that matter) actually have such
a statement?

Perl has a wonderful construct that looks like the proposed case
statement but can't quite be described in these terms. An example:

given ($x) {
$y = 'a' when $a;
$y = 'b' when $b;
$y = 'c' when $c;
}

The reason it's not exactly as described is that the "given" part and
the "when" parts are not connected syntactically. You can, for example,
have a set of "when" clauses in a "while" or "for" loop, and you don't
have to have any inside a "given" statement.

It's an extraordinarily powerful construct, mainly due to the magic
that a "when" clause can do.

Also, I remember an old variant of Algol called Algol-S had exactly
what's been proposed. I've not used it since 1978.
(BTW we are in 2012 now you know, with all this talk of Fortran I and OS
360. I think they were already obsolete when I started programming 35 years
ago...)

35 years ago system 360 was current. It's what I learnt to program on,
though the systems people hankered after a newer and faster 370...

<snip>
 
K

Keith Thompson

BartC said:
But I have found that people don't seem like useful extra syntax in their
favourite languages. Or perhaps more accurately, if their favourite language
doesn't have a particularly handy construction, they will defend the lack
of it to the death!

For C, there's a *lot* of resistance to any changes that would break
existing code.

New features that don't break existing code still have a very large
burden of proof that they're sufficiently useful to justify the
substantial cost of (a) defining them rigorously, and (b) implementing
them in *all* conforming implementations. The agonizingly slow adoption
of C99 is a prime example of what can happen when that's ignored -- or
even when it isn't.
So, we don't need an if-else version of switch, because we can just use
if-else, and the compiler will end up generating the same code anyway. But
like you say, there would never be a reason to progress beyond if-then-goto
in that case.

If you're talking about either changing the existing switch
statement, or adding a new kind of switch statement, that allows
non-constant labels and jumps to the first matching case, I honestly
don't see that it's much better than a sequence of if/else if/else
statements. Presumably it would test a given value against a
sequence of other values. Would those tests be limited to equality,
or would it permit "<", ranges, and so forth?

It would evaluate the given expression only once rather than
re-evaluating it for each test -- but that's trivally accomplished
by using a temporary variable.

Am I missing some significant advantage in expressive power, safety,
performance, or something else that would make a dynamic switch
worth adding to the core language?
 
G

glen herrmannsfeldt

(snip)
If you're talking about either changing the existing switch
statement, or adding a new kind of switch statement, that allows
non-constant labels and jumps to the first matching case, I honestly
don't see that it's much better than a sequence of if/else if/else
statements. Presumably it would test a given value against a
sequence of other values. Would those tests be limited to equality,
or would it permit "<", ranges, and so forth?

As the number of cases gets larger, it looks much more readable
compared to if/elseif/else.

Also, if you implement a binary search (tree of if/else) instead
of linear search (if/elseif/elseif... /else) it is a lot of work to
get right, the nesting levels look horrible, and it is pretty much
impossible to extend. (Not that you could do that with the first
match logic, though.)
It would evaluate the given expression only once rather than
re-evaluating it for each test -- but that's trivally accomplished
by using a temporary variable.
Am I missing some significant advantage in expressive power, safety,
performance, or something else that would make a dynamic switch
worth adding to the core language?

Seems to me that it has a big advantage in the cases where
it applies for large number of cases.

How often that happens in actual programs, I don't know.

-- glen
 
I

Ian Collins

If you're talking about either changing the existing switch
statement, or adding a new kind of switch statement, that allows
non-constant labels and jumps to the first matching case, I honestly
don't see that it's much better than a sequence of if/else if/else
statements. Presumably it would test a given value against a
sequence of other values. Would those tests be limited to equality,
or would it permit "<", ranges, and so forth?

It would evaluate the given expression only once rather than
re-evaluating it for each test -- but that's trivally accomplished
by using a temporary variable.

Am I missing some significant advantage in expressive power, safety,
performance, or something else that would make a dynamic switch
worth adding to the core language?

One use case for an extension to switch would be where the label type
doesn't have a built in equality operation. For example a syntax like:

switch( variable, binary comparison ) { }

would be useful for matching strings:

bool matchString( const char* s1, const char* s2 ) {
return strcmp( s1, s2 ) == 0;
}

switch( input, matchString )
{
case "one":
//
break;

case "two":
//
break;
}
 
R

Rui Maciel

Ian said:
One use case for an extension to switch would be where the label type
doesn't have a built in equality operation. For example a syntax like:

switch( variable, binary comparison ) { }

would be useful for matching strings:

bool matchString( const char* s1, const char* s2 ) {
return strcmp( s1, s2 ) == 0;
}

switch( input, matchString )
{
case "one":
//
break;

case "two":
//
break;
}

Why not let a function map a comparisson between matchString and a set of
strings to a set of integer/enum values, and then pass that value to a
switch?

<example>
#include <stdio.h>

/**
Compares string text with the set of n strings stored in matches[]
@param test string to be tested
@param matches set of n strings that will be compared with string test
@param n number of strings stored in matches[]
@return 0 if test matches no string, i+1 if test matches the i-th string
**/
int matchStrings(const char *test, const char *matches[], unsigned int n)
{
char const *tp, *mp; /* test pointer, matches pointer */

for(unsigned int i = 0; i < n; ++i)
{
tp = test;
mp = matches;

while( *tp != '\0' && *mp != '\0')
{
if(*tp != *mp)
break;
++tp;
++mp;
}

if( *tp == '\0' && *mp == '\0')
{
/* test matched match */
return i+1;
}
}

/* default return value: no match */
return 0;
}


int main(void)
{
char const *matches[] = {"one", "two", "three"};

switch(matchStrings("three", matches, 3) )
{
case 0:
puts("no match");
break;

case 1:
puts("matched one");
break;

case 2:
puts("matched two");
break;

case 3:
puts("matched three");
break;

default:
puts("some error occurred");
break;
}

return 0;
}
</code>


No need to bloat the C programming language to be able to pull this off.


Rui Maciel
 
I

Ian Collins

Why not let a function map a comparisson between matchString and a set of
strings to a set of integer/enum values, and then pass that value to a
switch?

Less to type!
 
R

Rosario1903

To me, "technical goodness" has "it works" as a prerequisite.
If it doesn't work, it can't be technically good. I'm just not
interested in elegant failures.

:) i agree...
 
G

glen herrmannsfeldt

Rui Maciel said:
Ian Collins wrote:
Why not let a function map a comparisson between matchString and a set of
strings to a set of integer/enum values, and then pass that value to a
switch?

Doesn't that just move the problem around?

It seems that String case might be added to Java in a future
version, but you could just case on the hashCode() of a String.

If the String hash function is fixed, you could just calculate
the hashCodes.

switch(str.hashCode) {
case "abc".hashCode():

except that, as far as I know, hashCode isn't evaluate at compile
time, so it is back to the run-time evaluation problem.

One could precompute the hashCode values, check that there
aren't any collisions, and put those in.

-- glen
 
B

BartC

Keith Thompson said:
statements. Presumably it would test a given value against a
sequence of other values.

That's the main thing.

Would those tests be limited to equality,
or would it permit "<", ranges, and so forth?

Even limiting switch to just matching an integer expression against a number
constant values, there's a bunch of things that are more useful to get
right first:

o Allow case 10,20,30,40,50: instead of case 10: case 20: case 30: case 40:
case 50:

o Allow case 1..5: instead of case 1: case 2: case 3: case 4: case 5:

o Although not so important if the above is present, allow mixed scalars and
ranges: case 1..5,7..10: (but the comma is a problem in C)

o Get rid of the need for break (but that would need an alternative keyword
for switch, and perhaps for case, to form a new syntax where break is not
needed and case labels are well-behaved (not allowed in every conceivable
place).

o Possibly, allow switch to return a value (although I mainly use such a
feature in a streamlined version of switch, where the case values are
omitted and assumed to be (0,) 1, 2, 3 ..., and with an abbreviated syntax.
In C, that might look like:

x = (n ? a, b, a+b : z);

if you excuse the commas again. Assign a, b or a+b to x when n is 0, 1 or 2,
otherwise z. Only one right-side-side value is evaluated).
It would evaluate the given expression only once rather than
re-evaluating it for each test -- but that's trivally accomplished
by using a temporary variable.

Am I missing some significant advantage in expressive power, safety,
performance, or something else that would make a dynamic switch
worth adding to the core language?

I use another version of switch when:

o I don't care whether a jumptable is created
o Integer case values are too big or disparate to form a jump table
o Non-integer case values are used
o Non-constant case values are being tested

That last one is the proposal here, but I have say there is very rarely a
need for that (in my own code); the other reasons are more likely ones to
use this alternate (in my case) form of switch. But why not allow it anyway?
Just to have the 'expressive power' when you need it.
 
B

BartC

Ian Collins said:
On 11/22/12 13:47, Keith Thompson wrote:

One use case for an extension to switch would be where the label type
doesn't have a built in equality operation. For example a syntax like:

That's a totally different kind of use.
switch( variable, binary comparison ) { }

would be useful for matching strings:

bool matchString( const char* s1, const char* s2 ) {
return strcmp( s1, s2 ) == 0;
}

switch( input, matchString )
{
case "one":
//
break;

case "two":
//
break;
}

You don't really need the matchString thing. Usually only == matching makes
sense for strings. Better to have a streamlined version just for that
purpose:

strswitch (input) {
case "one": ...
case "two": ...
default:
}

Use the opportunity to get rid of break, too! (That was a bad mistake in the
original switch statement.)

Also the compiler can not optimise the matching of these strings, by using
one of the usual search techniques for example.

(It's possible to just use a string table, and a function, to do this lookup
now, but that doesn't give you the convenience of placing the handler code
directly against each string.)
 
B

BartC

If it isn't needed all that often, maybe it isn't worth adding.

There is cost in the complexity of compilers, and the ability of people
to remember how to use new features.

Not in syntax. That's one of the easiest parts of a compiler.

In C however everyone is on the one hand encouraged to use macros to
overcome shortcomings in the syntax ('there really is no need for such a
feature because here's a simple macro to do it'); and on the other hand,
discouraged to use tacky macros, implemented in a different way by each
programmer, because it makes the code unreadable to others! Because
effectively each is creating their own dialect.

For example, I hate the C for-statement, since there's a lot of typing, and
things to mistype or get wrong, for a simple A to B iteration, or N-times
repeat.

So in the quite a few thousand lines of C code I've written over the last
few weeks, I've extensively used macros such as FOR(I,A,B) or TO(I,N) (which
just repeats some code N times; I don't need the index, but the macro is
simpler with it).

I've used these dozens of times; the normal 'for' statement I've used twice
(to countdown from B to A instead, and I haven't got round to doing a
downward-counting FOR macro!)

So if I have a problem with a bit of code, I can't just post it on here. But
I don't care! The macros make like life a lot simpler.

But obviously the need is there, so why not have it part of the language? As
I said, adding syntax has virtually zero-cost, but can save costs on
development.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,077
Messages
2,570,567
Members
47,204
Latest member
abhinav72673

Latest Threads

Top