Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > some well known stupidness in c99

Reply
Thread Tools

some well known stupidness in c99

 
 
Keith Thompson
Guest
Posts: n/a
 
      11-22-2012
"BartC" <> writes:
[...]
> 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?

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
glen herrmannsfeldt
Guest
Posts: n/a
 
      11-22-2012
Keith Thompson <kst-> wrote:

(snip)
>> 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?


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
 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      11-22-2012
On 11/22/12 13:47, Keith Thompson wrote:
>
> 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;
}

--
Ian Collins
 
Reply With Quote
 
Rui Maciel
Guest
Posts: n/a
 
      11-22-2012
Ian Collins 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:
>
> 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[i];

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

if( *tp == '\0' && *mp == '\0')
{
/* test matched match[i] */
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
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      11-22-2012
On 11/22/12 17:18, Rui Maciel wrote:
> Ian Collins 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:
>>
>> 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?


Less to type!

--
Ian Collins
 
Reply With Quote
 
Rosario1903
Guest
Posts: n/a
 
      11-22-2012
On Wed, 21 Nov 2012 13:43:07 -0500, Eric Sosman wrote:

> 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...
 
Reply With Quote
 
glen herrmannsfeldt
Guest
Posts: n/a
 
      11-22-2012
Rui Maciel <> wrote:
> Ian Collins 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:


>> 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?


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

 
Reply With Quote
 
BartC
Guest
Posts: n/a
 
      11-22-2012
"Keith Thompson" <kst-> wrote in message
news:...
> "BartC" <> writes:


> 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.

--
Bartc

 
Reply With Quote
 
BartC
Guest
Posts: n/a
 
      11-22-2012
"Ian Collins" <ian-> wrote in message
news:...
> On 11/22/12 13:47, Keith Thompson wrote:


>> 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:


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.)

--
Bartc

 
Reply With Quote
 
BartC
Guest
Posts: n/a
 
      11-22-2012
"glen herrmannsfeldt" <> wrote in message
news:k8jmia$pdg$...
> BartC <> wrote:


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


> 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.

--
Bartc

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Is this phase-accumulator trick well-known??? Mike Treseler VHDL 0 02-08-2009 07:17 PM
List mutation method gotcha - How well known? Hendrik van Rooyen Python 20 03-16-2008 09:55 AM
Difference between "library parts" of C99 and "language parts" of C99 albert.neu@gmail.com C Programming 3 03-31-2007 08:14 PM
C99 struct initialization (C99/gcc) jilerner@yahoo.com C Programming 3 02-20-2006 04:41 AM
well-known Internet sites which use Java based web servers Mladen Adamovic Java 3 10-24-2005 09:48 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57