krste@ICSI.Berkeley.EDU ( Krste Asanovic) (08/08/90)
The C/C++ switch statement is very limited as it only allows integer
expressions. I'd like to suggest a more general case statement.
The syntax would be,
case (exp) {
case val1 : s1;
case val2 : s2;
default : sOther;
}
This uses the already reserved keyword case, followed by a
parenthesised expression, to introduce the construct. The standard
switch case and default labels would be used as before. The limitation
that case label expressions are compile-time constants would be
removed (although optimizing compilers could check for this case). The
limitation that case labels be unique would be removed (can't check
this at run time), but the order in which case expressions were tested
would be undefined. Comparisions would use the appropriate ==
operator, in the above example the tests would be
if (exp.operator==(val1)) ..s1... \ in undefined order.
if (exp.operator==(val2)) ..s2... /
henry@zoo.toronto.edu (Henry Spencer) (08/08/90)
In article <26842@pasteur.Berkeley.EDU> krste@ICSI.Berkeley.EDU ( Krste Asanovic) writes: >The C/C++ switch statement is very limited as it only allows integer >expressions. I'd like to suggest a more general case statement. >The syntax would be, > > case (exp) { > case val1 : s1; > case val2 : s2; > default : sOther; > } Try this, which is already legal C++: if (exp == val1) s1; else if (exp == val2) s2; else sOther; It is a bit less convenient to type, but does the job. I greatly doubt that X3J16 will sanction a new and untried feature which duplicates an existing one with only a trivial variation in syntax. -- The 486 is to a modern CPU as a Jules | Henry Spencer at U of Toronto Zoology Verne reprint is to a modern SF novel. | henry@zoo.toronto.edu utzoo!henry
bilmes@icsib.Berkeley.EDU (Jeff Bilmes) (08/09/90)
In article <26842@pasteur.Berkeley.EDU> krste@ICSI.Berkeley.EDU ( Krste Asanovic) writes: >The C/C++ switch statement is very limited as it only allows integer >expressions. I'd like to suggest a more general case statement. >The syntax would be, > > case (exp) { > case val1 : s1; > case val2 : s2; > default : sOther; > } > > ... I think this is unnecessary. C++ is already a large language and new features which don't have important semantic advantages should be avoided. The case statement you mention above would only add type checking and non compile time constants "switched" on in a (I presume) syntactically pleasing way. This does not warrant extending the language when you can do the semantic equivalent as easily as: if (exp == val1) s1 else if (exp == val2) s2 else if (exp == val3 || exp == val4 || exp == val5 || ...) s3 ... ---------------------------------------------------------- Jeff Bilmes arpa: bilmes@icsi.berkeley.edu uucp: ...!ucbvax!icsi!bilmes
bobatk@microsoft.UUCP (Bob ATKINSON) (08/14/90)
In article <26857@pasteur.Berkeley.EDU> bilmes@icsib (Jeff Bilmes) writes: >In article <26842@pasteur.Berkeley.EDU> krste@ICSI.Berkeley.EDU ( Krste Asanovic) writes: >>The C/C++ switch statement is very limited as it only allows integer >>expressions. ... > >This does not warrant >extending the language when you can do the semantic equivalent as >easily as: > > if (exp == val1) > s1 > else if (exp == val2) > s2 > else if (exp == val3 || exp == val4 || exp == val5 || ...) > s3 > ... By this logic, switch statements should not have been invented in the first place. Clearly in C a need was felt for this syntactic sugar. Krste was merely pointing out that one can argue that the same needs can motivate a similar extension for non-integral types, of which there are a significantly larger number in C++ (that have equality operators) than in C. I guess I don't feel particularly strongly about this issue; I just felt the reasoning being used was flawed. Bob Atkinson Microsoft
scott@bbxsda.UUCP (Scott Amspoker) (08/14/90)
In article <56515@microsoft.UUCP> bobatk@microsoft.UUCP (Bob ATKINSON) writes: >In article <26857@pasteur.Berkeley.EDU> bilmes@icsib (Jeff Bilmes) writes: >>This does not warrant >>extending the language when you can do the semantic equivalent as >>easily as: >> >> if (exp == val1) >> s1 >> else if (exp == val2) >> s2 >> else if (exp == val3 || exp == val4 || exp == val5 || ...) >> s3 >> ... > >By this logic, switch statements should not have been invented >in the first place. Clearly in C a need was felt for this syntactic >sugar.... I disagree. A series of 'if' statements implies a sequence of tests to be performed. A 'switch' implies a multi-way branch in which any of the possible case values are equally likely to occur. This can be easily optimized by a compiler. Although the standard does not mandate it, a switch statement is expected, in most cases, to be implemented as a quick indirect-jump table. It is not unusual to have switches with over 100 cases which would not perform acceptably as a series of 'if' statements. Syntactical sugar indeed! It is difficult to expand the multiway-jump concept to include non-integral values. In those cases, a switch statement really is nothing more than a series of 'if's. -- Scott Amspoker Basis International, Albuquerque, NM (505) 345-5232 unmvax.cs.unm.edu!bbx!bbxsda!scott
xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) (08/14/90)
bobatk@microsoft.UUCP (Bob ATKINSON) writes: >bilmes@icsib (Jeff Bilmes) writes: >>krste@ICSI.Berkeley.EDU ( Krste Asanovic) writes: >>>The C/C++ switch statement is very limited as it only allows integer >>>expressions. >... >> >>This does not warrant >>extending the language when you can do the semantic equivalent as >>easily as: >> >> if (exp == val1) >> s1 >> else if (exp == val2) >> s2 >> else if (exp == val3 || exp == val4 || exp == val5 || ...) >> s3 >> ... > >By this logic, switch statements should not have been invented >in the first place. Clearly in C a need was felt for this syntactic >sugar. Krste was merely pointing out that one can argue that >the same needs can motivate a similar extension for non-integral >types, of which there are a significantly larger number in C++ >(that have equality operators) than in C. > >I guess I don't feel particularly strongly about this issue; >I just felt the reasoning being used was flawed. Perhaps, but there is a more important reason to leave things alone: there are well known problems with testing equality with, explicitly, floating point values, and an extension of the case statement, where the test is unobvious, to allow, explicitly, floating point case switches, would promote maintenance problems. When the test is done with the "else if" paradigm, the use of the equality test is explicit, obvious, and thus easier to spot as a possible source of trouble during maintenance. Just a thought. Kent, the man from xanth. <xanthian@Zorch.SF-Bay.ORG> <xanthian@well.sf.ca.us>
rpk@wheaties.ai.mit.edu (Robert Krajewski) (08/15/90)
In article <962@bbxsda.UUCP> scott@bbxsda.UUCP (Scott Amspoker) writes: >I disagree. A series of 'if' statements implies a sequence of tests >to be performed. A 'switch' implies a multi-way branch in which any >of the possible case values are equally likely to occur. This can >be easily optimized by a compiler. Although the standard does not >mandate it, a switch statement is expected, in most cases, to be >implemented as a quick indirect-jump table. Let the compiler decide that, then. switch should just specify semantics. >It is not unusual to have switches with over 100 cases which would >not perform acceptably as a series of 'if' statements. Syntactical >sugar indeed! Well, there is one other benefit to switch: the switched thing is an expression, it is evaluated only once, right ? So you get a temporary for free if you need it. I would like to see switch be extended at least to cover data types for which == holds. It's unfortunate that case tags have to be constants, but I can live with that. -- Robert P. Krajewski Internet: rpk@ai.mit.edu ; Lotus: robert_krajewski.lotus@crd.dnet.lotus.com
perry@key.COM (Perry The Cynic) (08/18/90)
In article <9907@rice-chex.ai.mit.edu> rpk@rice-chex.ai.mit.edu (Robert Krajewski) writes: > In article <962@bbxsda.UUCP> scott@bbxsda.UUCP (Scott Amspoker) writes: > >I disagree. A series of 'if' statements implies a sequence of tests > >to be performed. A 'switch' implies a multi-way branch in which any > >of the possible case values are equally likely to occur. This can > >be easily optimized by a compiler. Although the standard does not > >mandate it, a switch statement is expected, in most cases, to be > >implemented as a quick indirect-jump table. > > Let the compiler decide that, then. switch should just specify > semantics. Exactly. A resonable compiler will compile a switch with two or three cases as an if/then/else sequence, internally. Often compilers also break up switches with large gaps between tag values. > >It is not unusual to have switches with over 100 cases which would > >not perform acceptably as a series of 'if' statements. Syntactical > >sugar indeed! > > Well, there is one other benefit to switch: the switched thing is > an expression, it is evaluated only once, right ? So you get a > temporary for free if you need it. > > I would like to see switch be extended at least to cover data types > for which == holds. It's unfortunate that case tags have to be constants, > but I can live with that. The problem here is that the compiler has no guarantee that a user-defined operator== provides the nice mathematical properties of true equality. For all the compiler knows, for a user-defined type T, "a==b && b==c" does not necessarily imply "a==c"; in fact it doesn't even guarantee "b==a". Yes, it's bad coding to violate these expected properties, but a compiler can't rely on "good form", only on the language standard. Thus, you'd have to carefully define whether switch (x) { case a: mumble(); } means if (x==a) mumble(); or if (a==x) mumble(); Neither interpretation strikes me as inherently more obvious. You don't really want to add this kind of confusion to the language. About non-constant case tags: The main problem with allowing non-constant case tags is precisely that the "switch" statement is intended as a "simultaneous choice" operation, not a sequential scan. Consider this example: switch (expr) { case foo(): mumble(); break; case bar(): tumble(); break; } How are foo() and bar() evaluated? Both, before a choice is made? In what order? If you *require* both foo() and bar() to be always evaluated, the compiler can't short-circuit things if it finds an early match, so the result would never be more efficient than an if-cascade. And what happens if foo() and bar() evaluate to the same value? Execute mumble() or tumble(), or both() (in what order :-)? This isn't a can of worms, it's a whole truck load. If you want a good laugh, try to interprete this: switch (n) { case n++: n--; mad(); break; case n++: n--; ness(); break; } Just to beat the dead horse into pulp, imagine that expr (and foo and bar) above are of a user-defined type with an operator== defined. Now the compiler is completely clue-less. It is possible that "expr==foo() && expr==bar()" but "foo() != bar()". To give well-defined semantics to this construct, we would have to rigidly define one particular order of evaluation for things. And that would indeed reduce this new construct to purely syntactic sugar on top of an if/then/else cascade. -- perry P.S.: If your main concern is the visual ugliness and confusion of long if-cascades, you can use the preprocessor to make your own syntax. I'm not sure that I would recomment that, though. -- -------------------------------------------------------------------------- Perry The Cynic (Peter Kiehtreiber) perry@arkon.key.com ** What good signature isn't taken yet? ** {amdahl,sgi,pacbell}!key!perry
rb@cc.ic.ac.uk (Robin Becker) (08/24/90)
There seems to be a fundamental reason why case/switch statements with variable/expression tags are to be avoided and that is the impossibility of guaranteeing that a unique tag will be selected. This means that either some ordering of tag interrogation has to be imposed which will kill optimisations (unless all tags are constant) or we abandon determinism and let the compiler decide. Of course this construct has been discussed before by Hoare, I seem to remember something about programs shouldn't depend on the order of guard evaluation. Even worse in parallel processing two guards may get evaluated to true so parallel languages like Occam must do something about this, but I don't know what.