By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,266 Members | 1,816 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,266 IT Pros & Developers. It's quick & easy.

C/C++ language proposal: Change the 'case expression' from "integral constant-expression" to "integral expression"

P: n/a
C/C++ language proposal:
Change the 'case expression' from "integral constant-expression" to "integral expression"

The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:

case constant-expression :

I propose that the case expression of the switch statement
be changed from "integral constant-expression" to "integral expression".
This opens up many new possibilities since then also function calls
would be permitted in the case expression.
The old case case would continue to function since
it is a subset of the new case case.

Example usage:

//...
int f()
{
//...
return BLA1;
}

int g()
{
//...
return BLA2;
}

int h()
{
//...
return BLA3;
}

int y, x = f();
switch (x)
{
case 123 : y = g(); break;
case g() : y = 456; break; // using new case feature, ie. func-call
case h() : y = 789; break; // ditto
default : y = -1; break;
}

Oct 23 '08 #1
Share this Question
Share on Google+
56 Replies


P: n/a
On October 23, 2008 14:17, in comp.lang.c, Adem (fo***********@alicewho.com)
wrote:
C/C++ language proposal:
Change the 'case expression' from "integral constant-expression" to
"integral expression"

The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:
[snip]

Sorry, but your proposal is off-topic for the comp.lang.c newsgroup. I
suspect that it is also off-topic for comp.lang.c++.

As C and C++ are two separate languages, each defined by their own
standards, I suggest that you break your "C/C++" proposal into a "C
proposal" and a separate "C++ proposal", and submit each to their
respective standards bodies.

For C, you /might/ post your proposal to the comp.std.c newsgroup, as that
is the group that discusses the ramifications of and enhancements to the C
language standard.

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
Oct 23 '08 #2

P: n/a
Adem wrote:
C/C++ language proposal:
Change the 'case expression' from "integral constant-expression" to "integral expression"

The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:

case constant-expression :

I propose that the case expression of the switch statement
be changed from "integral constant-expression" to "integral expression".
switch (rand()) {
case rand(): puts ("What's"); break;
case rand(): puts ("wrong"); break;
case rand(): puts ("with"); break;
case rand(): puts ("this"); break;
case rand(): puts ("picture?"); break;
}

--
Er*********@sun.com
Oct 23 '08 #3

P: n/a
Eric Sosman <Er*********@sun.comwrites:
Adem wrote:
>C/C++ language proposal: Change the 'case expression' from
"integral constant-expression" to "integral expression"
The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:
case constant-expression : I propose that the case expression
of the switch statement
be changed from "integral constant-expression" to "integral expression".

switch (rand()) {
case rand(): puts ("What's"); break;
case rand(): puts ("wrong"); break;
case rand(): puts ("with"); break;
case rand(): puts ("this"); break;
case rand(): puts ("picture?"); break;
}
Well, it *could* be defined to be equivalent to the following:

{
const int __tmp = rand();
if (__tmp == rand() puts("What's");
else if (__tmp == rand() puts("wrong");
else if (__tmp == rand() puts("with");
else if (__tmp == rand() puts("this");
else if (__tmp == rand() puts("picture?");
}

That's intended to be equivalent code just for this example, not a
definition; other transformations would be required when one case
falls through to the next. And I refuse to think about how this would
affect Duff's Device.

The point of C's switch statement is that it can be implemented
efficiently as a jump table, in contrast to an if/else chain where the
conditions have to be evaluated sequentially.

If you want to do something like a switch statement, but where the
case values aren't constant, you can always just write an if/else
chain. If you want to support this kind of thing in the language, so
that you only have to specify the LHS of the comparison once, I think
I'd prefer to introduce a new construct rather than adding this
functionality to the existing switch/case construct. With this
proposal, changing a single expression from a constant to a
non-constant could have substantial effects on the generated code, and
depending on how it's defined, subtle effects on the code's behavior.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 23 '08 #4

P: n/a
Lew Pitcher wrote:
Adem (fo***********@alicewho.com) wrote:
>C/C++ language proposal:
Change the 'case expression' from "integral constant-expression"
to "integral expression"

The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:

[snip]

Sorry, but your proposal is off-topic for the comp.lang.c
newsgroup. I suspect that it is also off-topic for comp.lang.c++.

As C and C++ are two separate languages, each defined by their
own standards, I suggest that you break your "C/C++" proposal
into a "C proposal" and a separate "C++ proposal", and submit
each to their respective standards bodies.

For C, you /might/ post your proposal to the comp.std.c newsgroup,
as that is the group that discusses the ramifications of and
enhancements to the C language standard.
In addition, it is a BAD IDEA. Eliminating the constant provision
prevents making efficient transfer tables. It even prevents
discovering that such tables are feasible (or not).

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Oct 23 '08 #5

P: n/a
In article <49**************@yahoo.com>, cb********@maineline.net wrote:
Lew Pitcher wrote:
Adem (fo***********@alicewho.com) wrote:
C/C++ language proposal:
Change the 'case expression' from "integral constant-expression"
to "integral expression"
[...]
In addition, it is a BAD IDEA. Eliminating the constant provision
prevents making efficient transfer tables. It even prevents
discovering that such tables are feasible (or not).
It doesn't eliminate the privision, it just makes it more difficult. In
effect, optimizing

switch ( f() )
{
case 1: { /* A */ } break;
case 2: { /* B */ } break;
case 3: { /* C */ } break;
case 4: { /* D */ } break;
}

becomes similar optimizing

int const x = f();
if ( x == 1 ) { /* A */ }
else if ( x == 2 ) { /* B */ }
else if ( x == 3 ) { /* C */ }
else if ( x == 4 ) { /* D */ }

since both involve an unchanging value and constant values being compared
to. A compiler could convert both into a jump table or binary search.
Oct 23 '08 #6

P: n/a
On Oct 24, 3:12 am, Keith Thompson <ks...@mib.orgwrote:
Eric Sosman <Eric.Sos...@sun.comwrites:
Adem wrote:
C/C++ language proposal: Change the 'case expression' from
"integral constant-expression" to "integral expression"
The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:
case constant-expression : I propose that the case expression
of the switch statement
be changed from "integral constant-expression" to "integral expression".
switch (rand()) {
case rand(): puts ("What's"); break;
case rand(): puts ("wrong"); break;
case rand(): puts ("with"); break;
case rand(): puts ("this"); break;
case rand(): puts ("picture?"); break;
}
Wonderful!
>
Well, it *could* be defined to be equivalent to the following:

{
const int __tmp = rand();
if (__tmp == rand() puts("What's");
else if (__tmp == rand() puts("wrong");
else if (__tmp == rand() puts("with");
else if (__tmp == rand() puts("this");
else if (__tmp == rand() puts("picture?");

}
If rand() generates equal random numbers frequently, is it meaningful?
Oct 24 '08 #7

P: n/a
lo***************@gmail.c0m wrote:
On Oct 24, 3:12 am, Keith Thompson <ks...@mib.orgwrote:
....
>Well, it *could* be defined to be equivalent to the following:

{
const int __tmp = rand();
if (__tmp == rand() puts("What's");
else if (__tmp == rand() puts("wrong");
else if (__tmp == rand() puts("with");
else if (__tmp == rand() puts("this");
else if (__tmp == rand() puts("picture?");

}

If rand() generates equal random numbers frequently, is it meaningful?
That code neither makes nor implies any assumptions about how frequently
rand() generates random numbers.
Oct 24 '08 #8

P: n/a

"Eric Sosman" <Er*********@sun.comwrote in message
news:1224788466.760836@news1nwk...
Adem wrote:
>C/C++ language proposal: Change the 'case expression' from "integral
constant-expression" to "integral expression"

The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:

case constant-expression : I propose that the case expression of
the switch statement
be changed from "integral constant-expression" to "integral expression".

switch (rand()) {
case rand(): puts ("What's"); break;
case rand(): puts ("wrong"); break;
case rand(): puts ("with"); break;
case rand(): puts ("this"); break;
case rand(): puts ("picture?"); break;
}
What's wrong with it that you're just injecting garbage. You can use the
same rand() trick with any statement:

for (i=rand(); i<=rand(); i=rand())...

But there's nothing really wrong with the OP's proposal, except it should be
a new statement type to keep the switch semantics clean. Then, it could also
use non-integer types.

C likes it's rather austere syntax however so I doubt this change will ever
be made.

--
Bartc

Oct 24 '08 #9

P: n/a
Bartc wrote:
>
"Eric Sosman" <Er*********@sun.comwrote in message
news:1224788466.760836@news1nwk...
>Adem wrote:
>>C/C++ language proposal: Change the 'case expression' from "integral
constant-expression" to "integral expression"

The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:

case constant-expression : I propose that the case expression
of the switch statement
be changed from "integral constant-expression" to "integral expression".

switch (rand()) {
case rand(): puts ("What's"); break;
case rand(): puts ("wrong"); break;
case rand(): puts ("with"); break;
case rand(): puts ("this"); break;
case rand(): puts ("picture?"); break;
}

What's wrong with it that you're just injecting garbage. You can use the
same rand() trick with any statement:

for (i=rand(); i<=rand(); i=rand())...

But there's nothing really wrong with the OP's proposal, except it
should be a new statement type to keep the switch semantics clean. Then,
it could also use non-integer types.
There is something wrong. Try to compile this example, and I hope you
figure whats wrong with his proposal :

int main()
{
int a = 3;
switch( a )
{
case 3:
a = 1;
break;
case 3:
a = 2;
break;
case 3:
a = 3;
break;
default:
a = 4;
}
}
Oct 24 '08 #10

P: n/a

"anon" <an**@no.invalidwrote in message
news:gd**********@news01.versatel.de...
Bartc wrote:
>>
"Eric Sosman" <Er*********@sun.comwrote in message
news:1224788466.760836@news1nwk...
>>Adem wrote:
C/C++ language proposal: Change the 'case expression' from "integral
constant-expression" to "integral expression"
>But there's nothing really wrong with the OP's proposal, except it should
be a new statement type to keep the switch semantics clean. Then, it
could also use non-integer types.

There is something wrong. Try to compile this example, and I hope you
figure whats wrong with his proposal :

int main()
{
int a = 3;
switch( a )
{
case 3:
a = 1;
break;
case 3:
a = 2;
break;
case 3:
a = 3;
break;
default:
a = 4;
}
}
The OP was talking about /expressions/ for case values. But because normal
switch likes it's values to be unique, I suggested a different statement.
This way duplicate case values can still be picked up instead of being
quietly converted to the new semantics:

a=x=y=z=3;

newswitch (a)
{
case x: ...
case y: ...
case z: ...
...
This would just select the first matching expression. No different from a
series of if/else statements as already noted, but more eloquent.

--
Bartc

Oct 24 '08 #11

P: n/a
Bartc wrote:
"anon" <an**@no.invalidwrote in message
news:gd**********@news01.versatel.de...
>Bartc wrote:
>>>
"Eric Sosman" <Er*********@sun.comwrote in message
news:1224788466.760836@news1nwk...
Adem wrote:
C/C++ language proposal: Change the 'case expression' from
"integral constant-expression" to "integral expression"
>>But there's nothing really wrong with the OP's proposal, except
it should be a new statement type to keep the switch semantics
clean. Then, it could also use non-integer types.

There is something wrong. Try to compile this example, and I hope
you figure whats wrong with his proposal :

int main()
{
int a = 3;
switch( a )
{
case 3:
a = 1;
break;
case 3:
a = 2;
break;
case 3:
a = 3;
break;
default:
a = 4;
}
}

The OP was talking about /expressions/ for case values. But because
normal switch likes it's values to be unique, I suggested a
different statement. This way duplicate case values can still be
picked up instead of being quietly converted to the new semantics:

a=x=y=z=3;

newswitch (a)
{
case x: ...
case y: ...
case z: ...
...
This would just select the first matching expression. No different
from a series of if/else statements as already noted, but more
eloquent.
Yes, it would work, just as it does for COBOL's EVALUATE statement - a
multiway if-statement

http://www.fluffycat.com/COBOL/Evaluate/
Wanna be more like COBOL? :-)
Bo Persson
Oct 24 '08 #12

P: n/a
On Oct 24, 7:59 pm, "Bartc" <b...@freeuk.comwrote:
"Eric Sosman" <Eric.Sos...@sun.comwrote in message
Adem wrote:
The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:
case constant-expression : I propose that the case expression of
the switch statement
be changed from "integral constant-expression" to "integral expression".
switch (rand()) {
case rand(): puts ("What's"); break;
case rand(): puts ("wrong"); break;
case rand(): puts ("with"); break;
case rand(): puts ("this"); break;
case rand(): puts ("picture?"); break;
}
What's wrong with it that you're just injecting garbage. You can use the
same rand() trick with any statement:

for (i=rand(); i<=rand(); i=rand())...
The statements following each case lable in a switch are intended to
be diffrent, while the body of for statement is the same for each
loop. Eric's trick illustrates that how bad an idean could that
proposal be.
Oct 24 '08 #13

P: n/a
"lo***************@gmail.c0m" <lo***************@gmail.comwrites:
On Oct 24, 7:59 pm, "Bartc" <b...@freeuk.comwrote:
>"Eric Sosman" <Eric.Sos...@sun.comwrote in message
Adem wrote:
The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:
case constant-expression : I propose that the case expression of
the switch statement
be changed from "integral constant-expression" to "integral expression".
switch (rand()) {
case rand(): puts ("What's"); break;
case rand(): puts ("wrong"); break;
case rand(): puts ("with"); break;
case rand(): puts ("this"); break;
case rand(): puts ("picture?"); break;
}
What's wrong with it that you're just injecting garbage. You can use the
same rand() trick with any statement:

for (i=rand(); i<=rand(); i=rand())...

The statements following each case lable in a switch are intended to
be diffrent, while the body of for statement is the same for each
loop. Eric's trick illustrates that how bad an idean could that
proposal be.
The expressions (not statements) are intended (required, in fact) to
be integer constant expressions. The proposal is to change that
requirement. It's moderately obvious that the requirement that no two
of the case expressions would also have to be relaxed, since it's not
possible in general to determine at compilation time whether two
non-constant expressions have the same value.

Defining consistent semantics for a modified switch statement is not
all that difficult. Presumably existing switch statements would have
to behave as they do now. Beyond that, there are several possible
ways to define the semantics and constraints for switch statements
that are currently invalid.

Eric's example demonstrates the need to define the semantics of this
proposed new feature. I don't think it demonstrates, by itself, that
it's a bad idea. If non-constant switch expressions were allowed, it
would be possible to write perfectly sensible code using the new
feature. It would also, as Eric demonstrated, be possible to write
very silly code using the new feature -- or using any of the
language's existing features.

I do agree that the proposed feature is a bad idea, but not because of
Eric's example. I think it's a bad idea because it would have to
define new semantics for an existing construct. Currently, if you
accidentally use a non-constant case expression, the compiler will
diagnose it as an error (and probably reject your program). Under the
proposal, the code would be valid, and would likely behave in a subtly
wrong manner and/or with poor performance. Evaluating the switch
expression and branching to the right case label is typically an O(1)
operation, if the compiler is able to generate a jump table. Add a
single non-constant expression, and it becomes O(N), where N is the
number of cases.

I wouldn't object as strongly to a new feature, with a distinct
syntax, that implements the proposed functionality, but I'd still
oppose it -- not because it's an inherently bad idea, but because the
benefit is IMHO outweighed by the cost of adding a new feature to the
language. There's nothing you could do with the proposed new feature
that you can't already do fairly straightforwardly using existing
features, namely an if/else chain and, if the switch expression is
complicated or has side effects, a temporary variable.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 24 '08 #14

P: n/a
anon wrote:
>
.... snip ...
>
There is something wrong. Try to compile this example, and I hope
you figure whats wrong with his proposal :

int main()
{
int a = 3;
switch( a )
{
case 3:
a = 1;
break;
case 3:
a = 2;
break;
case 3:
a = 3;
break;
default:
a = 4;
}
}
Your code works better if it is made legal:

int main(void) {
int a = 3;

switch( a ) {
case 3: a = 1;
break;
case 2: a = 2;
break;
case 1: a = 3;
break;
default: a = 4;
}
return 0;
}

Also, cross posting to c.l.c++ is not cool.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Oct 24 '08 #15

P: n/a
CBFalconer <cb********@yahoo.comwrites:
anon wrote:
>>
... snip ...
>>
There is something wrong. Try to compile this example, and I hope
you figure whats wrong with his proposal :

int main()
{
int a = 3;
switch( a )
{
case 3:
a = 1;
break;
case 3:
a = 2;
break;
case 3:
a = 3;
break;
default:
a = 4;
}
}

Your code works better if it is made legal:

int main(void) {
int a = 3;

switch( a ) {
case 3: a = 1;
break;
case 2: a = 2;
break;
case 1: a = 3;
break;
default: a = 4;
}
return 0;
}
Which completely and utterly misses the point.

The article that started this thread was a proposal to allow
non-constant case expressions. anon's point was that it would then
become impossible (or nearly so) to maintain the property that all
case expressions in a switch statement must have distinct values.
Your "correction" is valid C, but pointless; you might as well have
posted "int main(void) { }".
Also, cross posting to c.l.c++ is not cool.
Perhaps, but the topic of the thread is a proposed change to both C
and C++. Arguably the comp.std.* groups would have been better, but I
think comp.std.c++ is more or less dead these days. Since switch
statements have the same syntax and semantics in C and C++, it's not
entirely unreasonable to discuss a proposed change in both.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 25 '08 #16

P: n/a
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
....
>Which completely and utterly misses the point.
It's what Chuck does best. One should always play to one's strengths.

Oct 25 '08 #17

P: n/a
Adem wrote:
C/C++ language proposal:
Change the 'case expression' from "integral constant-expression" to "integral expression"

The C++ Standard (ISO/IEC 14882, Second edition, 2003-10-15)
says under 6.4.2(2) [see also 5.19]:

case constant-expression :

I propose that the case expression of the switch statement
be changed from "integral constant-expression" to "integral expression".
This opens up many new possibilities since then also function calls
would be permitted in the case expression.
In what way would your altered switch be superior to an if/else tree?

The primary reason to use a switch is that it may be translated at
compile-time into a jump table, but that benefit goes away if the
statements are not known until run-time. Languages like Ruby have
switches with run-time case expressions because they delay the
translation until run-time, anyway; such languages are using the syntax
to mean something very different from what the C switch means. IOW,
languages that provide case statements of the form you've suggested do
so only because they *can't* do what C and C++ do.
Oct 25 '08 #18

P: n/a
In article <gd**********@aioe.org>, fo***********@alicewho.com says...

[ ... ]
int y, x = f();
switch (x)
{
case 123 : y = g(); break;
case g() : y = 456; break; // using new case feature, ie. func-call
case h() : y = 789; break; // ditto
default : y = -1; break;
}
This has a number of ramifications that could make definition difficult.
For a few examples, how often would g() be evaluated in the switch
statement above? If both g() and h() returned the same value, which leg
would be taken?

--
Later,
Jerry.

The universe is a figment of its own imagination.
Oct 27 '08 #19

P: n/a
Jerry Coffin <jc*****@taeus.comwrites:
In article <gd**********@aioe.org>, fo***********@alicewho.com says...

[ ... ]
>int y, x = f();
switch (x)
{
case 123 : y = g(); break;
case g() : y = 456; break; // using new case feature, ie. func-call
case h() : y = 789; break; // ditto
default : y = -1; break;
}

This has a number of ramifications that could make definition difficult.
For a few examples, how often would g() be evaluated in the switch
statement above? If both g() and h() returned the same value, which leg
would be taken?
The person proposing the feature did not give enough information to
answer those questions. If the proposed feature were to be added to
the language, then the semantics would have to be worked out first;
doing so shouldn't be too difficult. Once that's done, the answers to
your questions become obvious rather than indeterminate. (Possibly in
some cases the execution would be implementation-defined, or
unspecified, or even undefined, but I'd prefer a simpler definition
that avoids that.)

In my preferred semantics, the above would be exactly equivalent to:

int y, x = f();
int __tmp = x;
if (__tmp == 123) y = g();
else if (__tmp == g()) y = 456;
else if (__tmp == h()) y = 789;
else y = -1;

The number of times g() is evaluated depends on the value of x and the
value returned by g(), which you haven't specified. If both g() and
h() return the same value, and that happens to be the value of x, then
y would be set to 456.

But, as I said, I think the whole thing is a bad idea.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 27 '08 #20

P: n/a
Adem wrote:
C/C++ language proposal:
Change the 'case expression' from "integral constant-expression" to "integral expression"
How about:

cond {
(foo == bar): ...; break;
(!bar && (baz == boo)): ...; /* fallthru */
default: ...; break;
}

In pseudo-grammar:

cond { [<expr>|default: <stmt>*]* }
Oct 28 '08 #21

P: n/a
Matthias Buelow <mk*@incubus.dewrites:
Adem wrote:
>C/C++ language proposal:
Change the 'case expression' from "integral constant-expression"
to "integral expression"

How about:

cond {
(foo == bar): ...; break;
(!bar && (baz == boo)): ...; /* fallthru */
default: ...; break;
}

In pseudo-grammar:

cond { [<expr>|default: <stmt>*]* }
One advantage of the switch statement is that the expression only has
to be written once; it's implicitly compared to each of the case label
expressions without being re-evaluated.

Your proposed "cond" statement lacks this advantage, and differs from
an if/else chain only in the ability to fall through from one case to
the next. The latter can easily be done with a goto statement. (Yes,
gotos are ugly; so is falling through from one case to the next. And
you can always restructure the code to avoid gotos.)

As for the grammar, I think you'd want to require a keyword, probably
"case", for each expression:

cond {
case foo == bar: ... break;
case !bar && (baz == boo): ...; /* fallthrough */
default: ...; break;
}

Otherwise the compiler doesn't know until it sees the ':' whether the
expression is part of the cond statement or just an ordinary
expression statement.

And of course it would break every existing program that uses "cond"
as a keyword, but that's easily solved by using "_Cond".

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 28 '08 #22

P: n/a
Keith Thompson <ks***@mib.orgwrites:
And of course it would break every existing program that uses "cond"
as a keyword,
ITYM "as an identifier,".

mlp
Oct 28 '08 #23

P: n/a
Mark L Pappin <ml*@acm.orgwrites:
Keith Thompson <ks***@mib.orgwrites:
>And of course it would break every existing program that uses "cond"
as a keyword,

ITYM "as an identifier,".
D'oh! Yes, thanks.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 28 '08 #24

P: n/a
On Oct 25, 10:43*am, Jeff Schwab <j...@schwabcenter.comwrote:
In what way would your altered switch be superior to an if/else tree?
Two ways:

1) An if/else tree hides the fact that the same variable is being
tested in each branch. A switch/case makes it clear that the same
expression is being compared in each case.

2) In some cases, it would make truly atrocious code look better. For
example, consider cases where you need to fall through from one case
to another or where you would otherwise need a temporary to avoid
multiple evaluations of the switch variable.
The primary reason to use a switch is that it may be translated at
compile-time into a jump table, but that benefit goes away if the
statements are not known until run-time. *Languages like Ruby have
switches with run-time case expressions because they delay the
translation until run-time, anyway; such languages are using the syntax
to mean something very different from what the C switch means. *IOW,
languages that provide case statements of the form you've suggested do
so only because they *can't* do what C and C++ do.
But they don't provide what he's asking for, and it's a natural
extension of the semantics of the switch/case statement. We could have
a special 'if' that allowed the implementation to cycle a specified
constant, either by counting up, down, or sideways if that was most
efficient. But we don't. We expect the optimizer to figure out how our
code can be micro-optimized.

Why do we have do/while, while, and for? You can make any code ugly by
choosing the wrong one, but you can make a lot of code nice by
choosing the best one.

The biggest argument against this proposal is that it's not really all
that useful. There really just aren't that many places where you could
use something like this.

In a 500,000 C++ line project I'm very familiar with, there are three
places where this could actually be useful. For comparison, it has 818
switch statements.

In two of those cases, it cleans up some ugliness where you need an if/
else tree before a switch/case statement.

What will be next? "case >=7:"?

DS
Oct 29 '08 #25

P: n/a
On Oct 28, 7:24 pm, Matthias Buelow <m...@incubus.dewrote:
Adem wrote:
C/C++ language proposal:
Change the 'case expression' from "integral
constant-expression" to "integral expression"
How about:
cond {
(foo == bar): ...; break;
(!bar && (baz == boo)): ...; /* fallthru */
default: ...; break;
}
In pseudo-grammar:
cond { [<expr>|default: <stmt>*]* }
I once designed a language with something like that, many, many
years back. In fact, the grammar was a bit more complete,
something like:

cond_stmt := 'cond' [<expr1>] '{' case_list '}'
case_list := /* empty */ | case_list case_clause
case_clause := 'case' [<op>] expr2 ':' stmt
| 'default' ':' stmt

If expr1 was absent, <opwas forbidden, and it worked exactly
like your suggestion (except that there was no fall through---a
case controlled exactly one statement). If expr1 was present,
it was the equivalent of having written "case <expr1<op>
<expr2>" for each case, except that expr1 was only evaluated
once; if you omitted the <opin this case, it defaulted to ==,
so you could write things like:

cond x {
case 0 : ... ;
case == 0 : ... ;
case < 0 : ... ;
}

or

cond c {
case 'a' : ... ;
case 'b' : ... ;
case 'c' : ... ;
}

(IIRC, the keyword was actually select, and not cond, and I used
OF .. END instead of {..}. But the basic idea was the same.)

The idea was basically that there are only four basic structured
constructs: a loop, a choice, a sequence, and a procedure call,
and thus, there were only four basic execution statements.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orient嶪 objet/
Beratung in objektorientierter Datenverarbeitung
9 place S幦ard, 78210 St.-Cyr-l'丱ole, France, +33 (0)1 30 23 00 34
Oct 29 '08 #26

P: n/a
On Oct 28, 7:42*pm, JoelKatz <dav...@webmaster.comwrote:
What will be next? "case >=7:"?

Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...
Oct 29 '08 #27

P: n/a
"ro***********@yahoo.com" <ro***********@yahoo.comwrites:
On Oct 28, 7:42*pm, JoelKatz <dav...@webmaster.comwrote:
>What will be next? "case >=7:"?

Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...
Then programmers will inevitably write

case 'A' ... 'Z':

which is non-portable (under EBCDIC it matches '\' and '}').

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 29 '08 #28

P: n/a
Keith Thompson wrote:
) Then programmers will inevitably write
)
) case 'A' ... 'Z':
)
) which is non-portable (under EBCDIC it matches '\' and '}').

In which case, it would be relatively easy to add syntax similar to:

case [A-Z]:

Which would, of course, be portable.
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
Oct 29 '08 #29

P: n/a
"ro***********@yahoo.com" <ro***********@yahoo.comwrites:
On Oct 28, 7:42*pm, JoelKatz <dav...@webmaster.comwrote:
>What will be next? "case >=7:"?


Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...
GCC provides this as an extension, FWIW. You can write

case 2 ... 5:

The spaces are required to keep the parser from thinking it's some
malformed floating point constant.
Oct 29 '08 #30

P: n/a
Willem <wi****@stack.nlwrites:
Keith Thompson wrote:
) Then programmers will inevitably write
)
) case 'A' ... 'Z':
)
) which is non-portable (under EBCDIC it matches '\' and '}').

In which case, it would be relatively easy to add syntax similar to:

case [A-Z]:

Which would, of course, be portable.
It could be, if you defined it *very* carefully.

Lexically, you have 7 tokens:
case (a keyword)
[ (a punctuator)
A (an identifier)
- (a punctuator)
Z (an identifier)
] (a punctuator)
: (a punctuator)

Do you really intend the identifier A here to refer to the character
'A', ignoring any declared entity called A? Do you really intend to
specify a range of literal character values without using the "'"
symbol? Which characters would be allowed? Does [A-Z] refer only to
the 26 uppercase letters of the Latin alphabet? Could this notation
be used for non-Latin letters? Digits? Punctuation symbols?

Properly defined, it could make it easier to work with Latin letters
-- which is both good and bad, since it would further encourage
programmers to ignore the fact that other alphabets exist. Sometimes
you really do want to determine whether a character matches one of the
26 uppercase Latin letters, but more often what you *really* want is
the locale-sensitive behavior of isupper().

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 29 '08 #31

P: n/a
Keith Thompson wrote:
) Willem <wi****@stack.nlwrites:
)In which case, it would be relatively easy to add syntax similar to:
)>
) case [A-Z]:
)>
)Which would, of course, be portable.
)
) It could be, if you defined it *very* carefully.
)
) <snip>
)
) Do you really intend the identifier A here to refer to the character
) 'A', ignoring any declared entity called A?

Well, no. That's why I stated 'similar to'. It's just an idea after all.

) programmers to ignore the fact that other alphabets exist. Sometimes
) you really do want to determine whether a character matches one of the
) 26 uppercase Latin letters, but more often what you *really* want is
) the locale-sensitive behavior of isupper().

Well, then how about

case [:upper:]:

Which, to be honest, is half-borrowed from Perl syntax.
What the exact syntax is, isn't really relevant, I guess.
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
Oct 29 '08 #32

P: n/a
Willem wrote:
[... case ranges for characters ...]
Well, then how about

case [:upper:]:

Which, to be honest, is half-borrowed from Perl syntax.
What the exact syntax is, isn't really relevant, I guess.
The syntax is less important than getting the semantics
right. One problem is in how to define the character classes;
note that isupper() et al. are locale-dependent, so the set of
characters that satisfy them is hard to compute at compile time.
And there's still the issue of ambiguous branches:

switch ('a') {
case isalpha(ch): ...
case islower(ch): ...
case isxdigit(ch): ...
case !ispunct(ch): ...

"These arguments sound very well, but I can't help
thinking that, if they were reduced to syllogistic form,
they wouldn't hold water." -- R. Murgatroyd

--
Er*********@sun.com
Oct 29 '08 #33

P: n/a
Eric Sosman wrote:
[...]
And there's still the issue of ambiguous branches:

switch ('a') {
case isalpha(ch): ...
case islower(ch): ...
case isxdigit(ch): ...
case !ispunct(ch): ...
Oh, botheration: I botched that one royally, didn't I? The
fragment ought to have been something like

ch = 'a';
switch (0) {
case !isalpha(ch): ...
case !islower(ch): ...
case !isxdigit(ch): ...
case !!ispunct(ch): ...

--
Er*********@sun.com
Oct 29 '08 #34

P: n/a
Keith Thompson writes:
>Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...

Then programmers will inevitably write

case 'A' ... 'Z':
They do anyway. #define ISUPPER(c) ('A' <= (c) && (c) <= 'Z'). E.g. to
check for the ASCII (or 7-bit Unicode) letters regardless of locale.
which is non-portable (under EBCDIC it matches '\' and '}').
--
Hallvard
Oct 29 '08 #35

P: n/a
Hallvard B Furuseth <h.**********@usit.uio.nowrites:
Keith Thompson writes:
>>Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...

Then programmers will inevitably write

case 'A' ... 'Z':

They do anyway. #define ISUPPER(c) ('A' <= (c) && (c) <= 'Z'). E.g. to
check for the ASCII (or 7-bit Unicode) letters regardless of locale.
>which is non-portable (under EBCDIC it matches '\' and '}').
Sure, but there's not much that can be done to discourage dumb macros.
Actually, there is: <ctype.halready has the locale-sensitive
isupper() function.

The problem with the proposed "..." notation is that it makes it easy
to do the wrong thing (assuming that the uppercase letters have
contiguous codes and run from 'A' to 'Z') *without* making it any
easier to do the right thing (using isupper() to determine whether a
character is an uppercase letter).

On the other hand, there are certainly times when case ranges would be
handy for numeric ranges, as opposed to character ranges, and using
them wouldn't cause any problems. Other languages do provide similar
constructs. And I suppose compilers could warn about 'A' ... 'Z'.

Caveat: Sometimes ('A' <= c && c <= 'Z') *is* exactly what you want,
if you're writing deliberately non-portable code.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 29 '08 #36

P: n/a
ro***********@yahoo.com wrote:
On Oct 28, 7:42 pm, JoelKatz <dav...@webmaster.comwrote:
>What will be next? "case >=7:"?


Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...
That was already included in microsoft fortran 5.1 (extension)
in 1990 :) :)
Oct 29 '08 #37

P: n/a
Sjouke Burry <bu*************@ppllaanneett.nnlllwrites:
ro***********@yahoo.com wrote:
>On Oct 28, 7:42 pm, JoelKatz <dav...@webmaster.comwrote:
>>What will be next? "case >=7:"?
Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...

That was already included in microsoft fortran 5.1 (extension)
in 1990 :) :)
Pascal had it long before that, and it's likely that other languages
had it even earlier. There's certainly ample precedent. The question
is whether the benefits would outweigh the disadvantages, especially
considering the ambiguity of ranges like 'A' ... 'Z'.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 29 '08 #38

P: n/a
Keith Thompson wrote:
"ro***********@yahoo.com" <ro***********@yahoo.comwrites:
>On Oct 28, 7:42 pm, JoelKatz <dav...@webmaster.comwrote:
>>What will be next? "case >=7:"?
Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...

Then programmers will inevitably write

case 'A' ... 'Z':

which is non-portable (under EBCDIC it matches '\' and '}').
And why exactly would that be worse than an 'if'-'else' chain
relying on ASCII?

Schobi
Oct 30 '08 #39

P: n/a
On 2008-10-30 07:10:13 -0400, Hendrik Schober <sp******@gmx.desaid:
Keith Thompson wrote:
>"ro***********@yahoo.com" <ro***********@yahoo.comwrites:
>>On Oct 28, 7:42 pm, JoelKatz <dav...@webmaster.comwrote:
What will be next? "case >=7:"?
Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...

Then programmers will inevitably write

case 'A' ... 'Z':

which is non-portable (under EBCDIC it matches '\' and '}').

And why exactly would that be worse than an 'if'-'else' chain
relying on ASCII?
An if-else chain in source code wouldn't rely on ASCII, but on the
source character set, which would, presumably, be EBCDIC when you're
targeting a machine that uses EBCDIC.

switch(ch)
{
case 'A':
case 'B':
case 'C':
case 'D':
....
}

Each character will be properly encoded, even though there are extra
characters in the middle of the capital letters in EBCDIC.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 30 '08 #40

P: n/a
Pete Becker wrote:
On 2008-10-30 07:10:13 -0400, Hendrik Schober <sp******@gmx.desaid:
>Keith Thompson wrote:
>>"ro***********@yahoo.com" <ro***********@yahoo.comwrites:
On Oct 28, 7:42 pm, JoelKatz <dav...@webmaster.comwrote:
What will be next? "case >=7:"?
Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...
Then programmers will inevitably write

case 'A' ... 'Z':

which is non-portable (under EBCDIC it matches '\' and '}').
And why exactly would that be worse than an 'if'-'else' chain
relying on ASCII?

An if-else chain in source code wouldn't rely on ASCII [...]
I'd expect most of the programmers I worked with, in the
absent of the 'switch' syntax proposed above, to write
if( x>='A' && x<='Z' )
which is just as wrong.

So allowing this for #switch' IMO wouldn't make anything
worse.

Schobi
Oct 30 '08 #41

P: n/a
Hendrik Schober <sp******@gmx.dewrites:
Keith Thompson wrote:
>"ro***********@yahoo.com" <ro***********@yahoo.comwrites:
>>On Oct 28, 7:42 pm, JoelKatz <dav...@webmaster.comwrote:
What will be next? "case >=7:"?
Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...
Then programmers will inevitably write
case 'A' ... 'Z':
which is non-portable (under EBCDIC it matches '\' and '}').

And why exactly would that be worse than an 'if'-'else' chain
relying on ASCII?
It wouldn't. The problem (as I think I've already said in this
thread) is that adding this syntax makes it much easier to check for
characters in the range 'A' to 'Z' *without* making it any easier to
check for characters that are uppercase letters.

It's not the least bit difficult to write bad code in C or C++ (this
is cross-posted), even with their current features, but let's not make
it even easier.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 30 '08 #42

P: n/a
On Wed, 29 Oct 2008 13:45:46 -0700, Keith Thompson wrote:
Caveat: Sometimes ('A' <= c && c <= 'Z') *is* exactly what you want, if
you're writing deliberately non-portable code.
It doesn't need to be *deliberately* non-portable. If you were
implementing your own C library, on an ASCII-based machine with minimal
locale support, this could be the best way to write isupper.
Oct 30 '08 #43

P: n/a
Willem wrote:
Keith Thompson wrote:
) Willem <wi****@stack.nlwrites:
) case [A-Z]:
)>
)Which would, of course, be portable.
case [:upper:]:

Which, to be honest, is half-borrowed from Perl syntax.
What the exact syntax is, isn't really relevant, I guess.
It wouldn't be relevant, except that there is a widely recognized
standard (POSIX). It is already largely supported in C++ by Boost.Regex:

http://www.boost.org/doc/libs/1_36_0...r_classes.html
Oct 30 '08 #44

P: n/a
Harald van D議k <tr*****@gmail.comwrites:
On Wed, 29 Oct 2008 13:45:46 -0700, Keith Thompson wrote:
>Caveat: Sometimes ('A' <= c && c <= 'Z') *is* exactly what you want, if
you're writing deliberately non-portable code.

It doesn't need to be *deliberately* non-portable. If you were
implementing your own C library, on an ASCII-based machine with minimal
locale support, this could be the best way to write isupper.
I'd call that deliberately non-portable, at least if you know what
you're doing.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 30 '08 #45

P: n/a
On Thu, 30 Oct 2008 12:05:18 -0700, Keith Thompson wrote:
Harald van D議k <tr*****@gmail.comwrites:
>On Wed, 29 Oct 2008 13:45:46 -0700, Keith Thompson wrote:
>>Caveat: Sometimes ('A' <= c && c <= 'Z') *is* exactly what you want,
if you're writing deliberately non-portable code.

It doesn't need to be *deliberately* non-portable. If you were
implementing your own C library, on an ASCII-based machine with minimal
locale support, this could be the best way to write isupper.

I'd call that deliberately non-portable, at least if you know what
you're doing.
I read your message as suggesting non-portable had to be a goal for 'A'<=c
&& c<='Z' to be the right thing. If you meant that non-portable can be
okay, just that you need to be aware of it, then agreed.
Oct 30 '08 #46

P: n/a
On 2008-10-30 14:49:12 -0400, Harald van D議k <tr*****@gmail.comsaid:
On Wed, 29 Oct 2008 13:45:46 -0700, Keith Thompson wrote:
>Caveat: Sometimes ('A' <= c && c <= 'Z') *is* exactly what you want, if
you're writing deliberately non-portable code.

It doesn't need to be *deliberately* non-portable. If you were
implementing your own C library, on an ASCII-based machine with minimal
locale support, this could be the best way to write isupper.
Probably not. A table of flags is best, because it handles all the
isxxx functions.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 30 '08 #47

P: n/a
Harald van D議k <tr*****@gmail.comwrites:
On Thu, 30 Oct 2008 12:05:18 -0700, Keith Thompson wrote:
>Harald van D議k <tr*****@gmail.comwrites:
>>On Wed, 29 Oct 2008 13:45:46 -0700, Keith Thompson wrote:
Caveat: Sometimes ('A' <= c && c <= 'Z') *is* exactly what you want,
if you're writing deliberately non-portable code.

It doesn't need to be *deliberately* non-portable. If you were
implementing your own C library, on an ASCII-based machine with minimal
locale support, this could be the best way to write isupper.

I'd call that deliberately non-portable, at least if you know what
you're doing.

I read your message as suggesting non-portable had to be a goal for 'A'<=c
&& c<='Z' to be the right thing. If you meant that non-portable can be
okay, just that you need to be aware of it, then agreed.
Exactly. Portability is good, all else being equal, but all else is
not always equal.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 30 '08 #48

P: n/a
Keith Thompson wrote:
Hendrik Schober <sp******@gmx.dewrites:
>Keith Thompson wrote:
>>"ro***********@yahoo.com" <ro***********@yahoo.comwrites:
On Oct 28, 7:42 pm, JoelKatz <dav...@webmaster.comwrote:
What will be next? "case >=7:"?
Frankly I think ranges on the case constant expressions would be a
more useful addition while staying with the basic philosophy of the C
switch statement. IOW, "case 2...5:", or something along those
lines. But still not something I'm loosing sleep over...
Then programmers will inevitably write
case 'A' ... 'Z':
which is non-portable (under EBCDIC it matches '\' and '}').
And why exactly would that be worse than an 'if'-'else' chain
relying on ASCII?

It wouldn't. [...]
Then I don't see how your above argument is valid.

Schobi
Oct 31 '08 #49

P: n/a
Hendrik Schober <sp******@gmx.dewrites:
Keith Thompson wrote:
>Hendrik Schober <sp******@gmx.dewrites:
>>Keith Thompson wrote:
[...]
>>>Then programmers will inevitably write
case 'A' ... 'Z':
which is non-portable (under EBCDIC it matches '\' and '}').
And why exactly would that be worse than an 'if'-'else' chain
relying on ASCII?
It wouldn't. [...]

Then I don't see how your above argument is valid.
Since you snipped my argument, I have no idea why you disagree with
it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 31 '08 #50

56 Replies

This discussion thread is closed

Replies have been disabled for this discussion.