www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - switch case for constants-only?

reply "Nick Sabalausky" <a a.a> writes:
I just noticed in D1 that the values for the cases in a switch must be known 
at compile-time (btw, the docs don't seem somewhat vague on that). Is this 
also true in D2? If so, I don't suppose we could get that changed before the 
book? It's a real PITA for dynamic code. 
Dec 05 2009
next sibling parent reply Don <nospam nospam.com> writes:
Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be known 
 at compile-time (btw, the docs don't seem somewhat vague on that). Is this 
 also true in D2? If so, I don't suppose we could get that changed before the 
 book? It's a real PITA for dynamic code. 

Switch with constant values is completely different to a switch statement with variables -- it's reasonable to expect O(1) case comparisons if all the values are known at compile time, but I think that's impossible with variable cases. Allowing switch with variable cases at the expense of constant cases would be a real PITA for non-dynamic code. You'd need some way of handling both.
Dec 05 2009
parent "Nick Sabalausky" <a a.a> writes:
"Don" <nospam nospam.com> wrote in message 
news:hfeilp$m1b$1 digitalmars.com...
 Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be 
 known at compile-time (btw, the docs don't seem somewhat vague on that). 
 Is this also true in D2? If so, I don't suppose we could get that changed 
 before the book? It's a real PITA for dynamic code.

Switch with constant values is completely different to a switch statement with variables -- it's reasonable to expect O(1) case comparisons if all the values are known at compile time, but I think that's impossible with variable cases.

So who's expecting switch with variable cases to be O(1)?
 Allowing switch with variable cases at the expense of constant cases would 
 be a real PITA for non-dynamic code. You'd need some way of handling both.

Well, yea, that's what I'm saying: it should handle both.
Dec 05 2009
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 05 Dec 2009 16:08:00 -0500, Nick Sabalausky <a a.a> wrote:

 I just noticed in D1 that the values for the cases in a switch must be  
 known
 at compile-time (btw, the docs don't seem somewhat vague on that). Is  
 this
 also true in D2? If so, I don't suppose we could get that changed before  
 the
 book? It's a real PITA for dynamic code.

you mean a real PITA to use if instead of switch? AFAIK, switch is the way it is to foster different optimizations by the compiler. I don't know if optimizations can be performed if the cases are dynamic. Also, what happens if two of the cases are dynamically the same? I think one of the optimizations is that the compiler can reorder the cases to make the testing more streamlined. -Steve
Dec 05 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message 
news:op.u4hhjisgeav7ka localhost.localdomain...
 On Sat, 05 Dec 2009 16:08:00 -0500, Nick Sabalausky <a a.a> wrote:

 I just noticed in D1 that the values for the cases in a switch must be 
 known
 at compile-time (btw, the docs don't seem somewhat vague on that). Is 
 this
 also true in D2? If so, I don't suppose we could get that changed before 
 the
 book? It's a real PITA for dynamic code.

you mean a real PITA to use if instead of switch?

For long "if else(x == y)" chains where the x is always the same? Yes, absolutely.
 AFAIK, switch is the  way it is to foster different optimizations by the 
 compiler.

If the only reason for switch were optimization, then switch would be useless because it would be easy for the compiler to detect: if(x == constVal1) {} else if(x == constVal2) {} // Etc And do the exact same optimizations.
 I don't know  if optimizations can be performed if the cases are dynamic.

Compared to the if-else chains? Probably not. But so what?
 Also, what  happens if two of the cases are dynamically the same?

Switch is a shorthand for a certain pattern of if-else chains, as such, it should behave the same by choosing the first and skipping the rest.
 I think one of the  optimizations is that the compiler can reorder the 
 cases to make the  testing more streamlined.

Ok, so it just won't do that with non-constant cases.
Dec 05 2009
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 12/05/2009 03:39 PM, Nick Sabalausky wrote:
 "Steven Schveighoffer"<schveiguy yahoo.com>  wrote in message
 news:op.u4hhjisgeav7ka localhost.localdomain...
 On Sat, 05 Dec 2009 16:08:00 -0500, Nick Sabalausky<a a.a>  wrote:

 I just noticed in D1 that the values for the cases in a switch must be
 known
 at compile-time (btw, the docs don't seem somewhat vague on that). Is
 this
 also true in D2? If so, I don't suppose we could get that changed before
 the
 book? It's a real PITA for dynamic code.

you mean a real PITA to use if instead of switch?

For long "if else(x == y)" chains where the x is always the same? Yes, absolutely.

More so than remembering to type break after each case block?
Dec 05 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Ellery Newcomer" <ellery-newcomer utulsa.edu> wrote in message 
news:hfekll$pbl$1 digitalmars.com...
 On 12/05/2009 03:39 PM, Nick Sabalausky wrote:
 "Steven Schveighoffer"<schveiguy yahoo.com>  wrote in message
 news:op.u4hhjisgeav7ka localhost.localdomain...
 On Sat, 05 Dec 2009 16:08:00 -0500, Nick Sabalausky<a a.a>  wrote:

 I just noticed in D1 that the values for the cases in a switch must be
 known
 at compile-time (btw, the docs don't seem somewhat vague on that). Is
 this
 also true in D2? If so, I don't suppose we could get that changed 
 before
 the
 book? It's a real PITA for dynamic code.

you mean a real PITA to use if instead of switch?

For long "if else(x == y)" chains where the x is always the same? Yes, absolutely.

More so than remembering to type break after each case block?

Good point, but that's really a separate issue.
Dec 05 2009
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 12/05/2009 04:19 PM, Nick Sabalausky wrote:
 "Ellery Newcomer"<ellery-newcomer utulsa.edu>  wrote in message
 More so than remembering to type break after each case block?

Good point, but that's really a separate issue.

I don't know about that. The issue seems to be you want switch to behave in a manner unlike that of any other language that I know of. It's different. It breaks convention. It's a useful divergence. It's a feature that should exist. But I contend it makes more sense to make a new construct which *is* equivalent to a certain pattern of nested ifs (switch isn't) and incorporate your feature into that than to shoehorn it into switch.
Dec 05 2009
next sibling parent BCS <none anon.com> writes:
Hello Ellery,

 On 12/05/2009 04:19 PM, Nick Sabalausky wrote:
 
 "Ellery Newcomer"<ellery-newcomer utulsa.edu>  wrote in message
 
 More so than remembering to type break after each case block?
 


behave in a manner unlike that of any other language that I know of.

Lisp has something that workd like this. (Not that I think D should change.)
 It's different. It breaks convention.
 It's a useful divergence. It's a feature that should exist. But I
 contend it makes more sense to make a new construct which *is*
 equivalent to a certain pattern of nested ifs (switch isn't) and
 incorporate your feature into that than to shoehorn it into switch.

vote += 0.1;
Dec 05 2009
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Ellery Newcomer" <ellery-newcomer utulsa.edu> wrote in message 
news:hfer6b$15d1$1 digitalmars.com...
 On 12/05/2009 04:19 PM, Nick Sabalausky wrote:
 "Ellery Newcomer"<ellery-newcomer utulsa.edu>  wrote in message
 More so than remembering to type break after each case block?

Good point, but that's really a separate issue.

I don't know about that. The issue seems to be you want switch to behave in a manner unlike that of any other language that I know of. It's different. It breaks convention. It's a useful divergence. It's a feature that should exist. But I contend it makes more sense to make a new construct which *is* equivalent to a certain pattern of nested ifs (switch isn't) and incorporate your feature into that than to shoehorn it into switch.

I definitely agree we need a new switch that isn't so stuck in C-land. And if we got it, I'd be perfectly happy to restrict all the new stuff to the newer switch and just let C-style switch atrophy into oblivion. But a new switch just doesn't seem to be happening :(. Also, I still don't see how there's any semantic difference between the current switch and the switch-like if-else chain other than just the fact that switch currently carries the restriction that the values being checked against must be unique and known at compile time.
Dec 05 2009
next sibling parent reply grauzone <none example.net> writes:
Nick Sabalausky wrote:
 "Ellery Newcomer" <ellery-newcomer utulsa.edu> wrote in message 
 It's a useful divergence. It's a feature that should exist. But I contend 
 it makes more sense to make a new construct which *is* equivalent to a 
 certain pattern of nested ifs (switch isn't) and incorporate your feature 
 into that than to shoehorn it into switch.

I definitely agree we need a new switch that isn't so stuck in C-land. And if we got it, I'd be perfectly happy to restrict all the new stuff to the newer switch and just let C-style switch atrophy into oblivion. But a new switch just doesn't seem to be happening :(.

You'd still need to keep around the old switch for stuff like Duff's Device. But I agree that it'd be nice to have a new switch for the following reasons: could use pattern matching instead of just a list of values, no redundant "case", no fallthrough by default, allow a more functional programming style.
Dec 05 2009
parent "Nick Sabalausky" <a a.a> writes:
"grauzone" <none example.net> wrote in message 
news:hfeu6p$1apu$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Ellery Newcomer" <ellery-newcomer utulsa.edu> wrote in message
 It's a useful divergence. It's a feature that should exist. But I 
 contend it makes more sense to make a new construct which *is* 
 equivalent to a certain pattern of nested ifs (switch isn't) and 
 incorporate your feature into that than to shoehorn it into switch.

I definitely agree we need a new switch that isn't so stuck in C-land. And if we got it, I'd be perfectly happy to restrict all the new stuff to the newer switch and just let C-style switch atrophy into oblivion. But a new switch just doesn't seem to be happening :(.

You'd still need to keep around the old switch for stuff like Duff's Device. But I agree that it'd be nice to have a new switch for the following reasons: could use pattern matching instead of just a list of values, no redundant "case", no fallthrough by default, allow a more functional programming style.

I have to admit, I'm so jealous of what I've seen of Nemerle's pattern matching (and it's metaprogramming), that I've been tempted to to give a shot at switching to it for things that don't strickly need system-level capabilities.
Dec 05 2009
prev sibling next sibling parent reply BCS <none anon.com> writes:
Hello Nick,

 Also, I still don't see how there's any semantic difference between
 the current switch and the switch-like if-else chain other than just
 the fact that switch currently carries the restriction that the values
 being checked against must be unique and known at compile time.
 

For one; fall thought (but that can be done with gotos or some really ugly nested if's: The other thing is that a compiler is free to be implemented a switch statement any way it wants including things like perfect hashes or (for strings) a RegEx style DFA. This does have semantic effects in the O() of the construct. I'll grant that what you are asking for is useful. But I will not go so far as to say that the current switch construct or even it's name (it has about as much to do with switch as for has to do with while) should be co opted for it. I'll even go so far as to say that I really doubt that the current switch will atrophy even if another construct is added with these features.
Dec 05 2009
parent "Nick Sabalausky" <a a.a> writes:
"BCS" <none anon.com> wrote in message 
news:a6268ffdcba8cc43e0db895786 news.digitalmars.com...
 Hello Nick,

 Also, I still don't see how there's any semantic difference between
 the current switch and the switch-like if-else chain other than just
 the fact that switch currently carries the restriction that the values
 being checked against must be unique and known at compile time.

For one; fall thought (but that can be done with gotos or some really ugly nested if's:

Right, it all maps out.
 The other thing is that a compiler is free to be implemented a switch 
 statement any way it wants including things like perfect hashes or (for 
 strings) a RegEx style DFA. This does have semantic effects in the O() of 
 the construct.

I'd consider that more a matter of optimization. I know there's a lot of people here that disagree with me on this, but I don't consider time complexity a semantics issue, except for very, very explicit cases or possibly for (true) real-time.
 I'll grant that what you are asking for is useful. But I will not go so 
 far as to say that the current switch construct or even it's name (it has 
 about as much to do with switch as for has to do with while)

*shrug* I've alwayd thought of while as nothing more than (a very welcome) syntactic sugar for 'for'.
 should be co opted for it. I'll even go so far as to say that I really 
 doubt that the current switch will atrophy even if another construct is 
 added with these features.

 

Dec 05 2009
prev sibling parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 12/05/2009 06:25 PM, Nick Sabalausky wrote:
 Also, I still don't see how there's any semantic difference between the
 current switch and the switch-like if-else chain other than just the fact
 that switch currently carries the restriction that the values being checked
 against must be unique and known at compile time.

If I understand switch correctly, it is analogous to this: a = x; if( a == exp1) goto Case1; if( a == exp2) goto Case2; ... if( a == expN) goto CaseN; assert(0); Case1: ... Case2: ... ... CaseN: ... except that the case expressions aren't required to be in any order and the compiler has a fair amount of freedom in implementing those conditional jumps. Conceivably, you could even forgo the if statements and have computed goto statements if your cases are nice enough. Also note the value being compared doesn't change while it is being compared. If statements are a bit less disciplined in that regard.
Dec 05 2009
prev sibling next sibling parent reply div0 <div0 users.sourceforge.net> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Ellery Newcomer wrote:
 On 12/05/2009 04:19 PM, Nick Sabalausky wrote:
 "Ellery Newcomer"<ellery-newcomer utulsa.edu>  wrote in message
 More so than remembering to type break after each case block?

Good point, but that's really a separate issue.

I don't know about that. The issue seems to be you want switch to behave in a manner unlike that of any other language that I know of. It's different. It breaks convention.

PHP allows runtime vars as cases in switch. Though whether anybody round here considers PHP a real language is another matter. I'm in favour; requiring the case statements to be constants seem to be an optimisation requirement, rather than there being some actual reason for it. - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFLGwYmT9LetA9XoXwRAkd8AJ9m0MapxiSSpWnQ19Xcsh26LO/qgQCgm9+t QocozVfJymylNHD76L4Pbq0= =qE1v -----END PGP SIGNATURE-----
Dec 05 2009
parent "Nick Sabalausky" <a a.a> writes:
"div0" <div0 users.sourceforge.net> wrote in message 
news:hff0n1$1f6t$1 digitalmars.com...
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1

 Ellery Newcomer wrote:
 On 12/05/2009 04:19 PM, Nick Sabalausky wrote:
 "Ellery Newcomer"<ellery-newcomer utulsa.edu>  wrote in message
 More so than remembering to type break after each case block?

Good point, but that's really a separate issue.

I don't know about that. The issue seems to be you want switch to behave in a manner unlike that of any other language that I know of. It's different. It breaks convention.

PHP allows runtime vars as cases in switch. Though whether anybody round here considers PHP a real language is another matter.

PHP is very real. Just like Cancer and AIDS. ;)
Dec 05 2009
prev sibling parent "Steven E. Harris" <seh panix.com> writes:
BCS <none anon.com> writes:

 Lisp has something that workd like this.

Did you mean the "case" family=B9 of forms? ,---- | CL-USER> (case 3 | (1 "foo") | (2 "bar") | (otherwise "baz")) | "baz" | CL-USER> (case 4 | (1 "foo") | ((2 4) "bar") | (otherwise "baz")) | "bar" `---- There's also the similar "typecase" family=B2. Footnotes:=20 =B9 http://www.lispworks.com/documentation/HyperSpec/Body/m_case_.htm =B2 http://www.lispworks.com/documentation/HyperSpec/Body/m_tpcase.htm --=20 Steven E. Harris
Dec 05 2009
prev sibling next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
Nick Sabalausky Wrote:

 I just noticed in D1 that the values for the cases in a switch must be known 
 at compile-time (btw, the docs don't seem somewhat vague on that). Is this 
 also true in D2? If so, I don't suppose we could get that changed before the 
 book? It's a real PITA for dynamic code. 

int x = 1, y = 1; switch( z ) { case x: ... case y: ... } What should this do? Throw an exception perhaps?
Dec 05 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Sean Kelly" <sean invisibleduck.org> wrote in message 
news:hfelka$rhf$1 digitalmars.com...
 Nick Sabalausky Wrote:

 I just noticed in D1 that the values for the cases in a switch must be 
 known
 at compile-time (btw, the docs don't seem somewhat vague on that). Is 
 this
 also true in D2? If so, I don't suppose we could get that changed before 
 the
 book? It's a real PITA for dynamic code.

int x = 1, y = 1; switch( z ) { case x: ... case y: ... } What should this do? Throw an exception perhaps?

As I mentioned earlier, that should be semantically equivilent to: int x = 1, y = 1; if(z == x) { ... } else if(z == y) { ... } In fact, it's already semantically equivilent to that, except that x and y are currently required to be known at compile-time.
Dec 05 2009
next sibling parent reply Rainer Deyke <rainerd eldwood.com> writes:
Nick Sabalausky wrote:
 As I mentioned earlier, that should be semantically equivilent to:
 
 int x = 1, y = 1;
 
 if(z == x)
 { ... }
 else if(z == y)
 { ... }
 
 In fact, it's already semantically equivilent to that, except that x and y 
 are currently required to be known at compile-time.

I assume the same rule applies to 'goto case'? int i = 0, j = 0; switch (0) { case i: goto case j; // Oops, infinite loop. case j: // Never reached. } I'm basically in favor of this change - it increases the expressive power and uniformity of the language at little cost - but corner cases like this bother me. -- Rainer Deyke - rainerd eldwood.com
Dec 05 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Rainer Deyke" <rainerd eldwood.com> wrote in message 
news:hfenkl$veq$1 digitalmars.com...
 Nick Sabalausky wrote:
 As I mentioned earlier, that should be semantically equivilent to:

 int x = 1, y = 1;

 if(z == x)
 { ... }
 else if(z == y)
 { ... }

 In fact, it's already semantically equivilent to that, except that x and 
 y
 are currently required to be known at compile-time.

I assume the same rule applies to 'goto case'? int i = 0, j = 0; switch (0) { case i: goto case j; // Oops, infinite loop. case j: // Never reached. } I'm basically in favor of this change - it increases the expressive power and uniformity of the language at little cost - but corner cases like this bother me.

I think that amounts to a computed goto, which I don't think D currently has, so that probably just wouldn't compile. But with or without computerd goto, this sounds like a reason to use an actual fallthrough command instead of "goto case".
Dec 05 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Nick Sabalausky wrote:
 "Rainer Deyke" <rainerd eldwood.com> wrote in message 
 news:hfenkl$veq$1 digitalmars.com...
 I assume the same rule applies to 'goto case'?

I think that amounts to a computed goto, which I don't think D currently has, so that probably just wouldn't compile.

So case labels could be variables but labels for 'goto case' would be constant? That seems backwards and inconsistent. It also fails to address this: int i = 0, j = 0; switch (j) { case i: break; case j: // Never reached. }
 But with or without computerd goto, this sounds like a reason to use an 
 actual fallthrough command instead of "goto case".

Not really. If you want fallthrough, use 'goto case' without a label, like this: goto case; -- Rainer Deyke - rainerd eldwood.com
Dec 05 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Rainer Deyke" <rainerd eldwood.com> wrote in message 
news:hfeu0m$1af9$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Rainer Deyke" <rainerd eldwood.com> wrote in message
 news:hfenkl$veq$1 digitalmars.com...
 I assume the same rule applies to 'goto case'?

I think that amounts to a computed goto, which I don't think D currently has, so that probably just wouldn't compile.

So case labels could be variables but labels for 'goto case' would be constant? That seems backwards and inconsistent.

I guess I don't see it as inconsistent because I don't see case labels quite so much as goto labels but moreso as just an (awkward) syntax for pattern matching.
 It also fails to
 address this:

 int i = 0, j = 0;
 switch (j) {
 case i:
  break;
 case j:
  // Never reached.
 }

I don't see why it would need to. Switch compares values, not identifiers. If that needed to be addressed, then this would also need to be addressed: int i = 0, j = 0; if(j == i) {} else if(j == j) { /+ never reached +/ } And maybe you could argue that does need to be addressed too, but at that point it's no longer an issue of switch accepting or rejecting run-time values.
 But with or without computerd goto, this sounds like a reason to use an
 actual fallthrough command instead of "goto case".

Not really. If you want fallthrough, use 'goto case' without a label, like this: goto case;

Ahh, yea, good point. Does that currently work?
Dec 05 2009
parent Rainer Deyke <rainerd eldwood.com> writes:
Nick Sabalausky wrote:
 "Rainer Deyke" <rainerd eldwood.com> wrote in message 
 news:hfeu0m$1af9$1 digitalmars.com...
 So case labels could be variables but labels for 'goto case' would be
 constant?  That seems backwards and inconsistent.

I guess I don't see it as inconsistent because I don't see case labels quite so much as goto labels but moreso as just an (awkward) syntax for pattern matching.

The question is how to make 'goto case' work with the improved switch statements without breaking compatibility or creating an artificial distinction between static and dynamic switch statements. The obvious solution is to rewrite this: switch (n) { case a: goto case b; ... } ...as this: __switch_value = n; __switch_start: switch (__switch_value) { case a: __switch_value = b; goto __switch_start; ... } This rewrite preserves the current semantics of 'goto case' while allowing the case label to be an arbitrary expression, both in the actual label and in the 'goto case' statement. The "computed goto" effect is a natural consequence of the rewrite.
 It also fails to
 address this:

I don't see why it would need to.

It doesn't need to, but it makes 'switch' statements slightly more error-prone. That's a small but real and measurable loss.
 goto case;

Ahh, yea, good point. Does that currently work?

It should. I don't have a D compiler around to test it. -- Rainer Deyke - rainerd eldwood.com
Dec 05 2009
prev sibling next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
Nick Sabalausky Wrote:

 "Sean Kelly" <sean invisibleduck.org> wrote in message 
 news:hfelka$rhf$1 digitalmars.com...
 Nick Sabalausky Wrote:

 I just noticed in D1 that the values for the cases in a switch must be 
 known
 at compile-time (btw, the docs don't seem somewhat vague on that). Is 
 this
 also true in D2? If so, I don't suppose we could get that changed before 
 the
 book? It's a real PITA for dynamic code.

int x = 1, y = 1; switch( z ) { case x: ... case y: ... } What should this do? Throw an exception perhaps?

As I mentioned earlier, that should be semantically equivilent to: int x = 1, y = 1; if(z == x) { ... } else if(z == y) { ... } In fact, it's already semantically equivilent to that, except that x and y are currently required to be known at compile-time.

D allows duplicate case values? I thought this was a compile error.
Dec 05 2009
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Sean Kelly" <sean invisibleduck.org> wrote in message 
news:hfeqbg$143u$1 digitalmars.com...
 Nick Sabalausky Wrote:

 "Sean Kelly" <sean invisibleduck.org> wrote in message
 news:hfelka$rhf$1 digitalmars.com...
 Nick Sabalausky Wrote:

 I just noticed in D1 that the values for the cases in a switch must be
 known
 at compile-time (btw, the docs don't seem somewhat vague on that). Is
 this
 also true in D2? If so, I don't suppose we could get that changed 
 before
 the
 book? It's a real PITA for dynamic code.

int x = 1, y = 1; switch( z ) { case x: ... case y: ... } What should this do? Throw an exception perhaps?

As I mentioned earlier, that should be semantically equivilent to: int x = 1, y = 1; if(z == x) { ... } else if(z == y) { ... } In fact, it's already semantically equivilent to that, except that x and y are currently required to be known at compile-time.

D allows duplicate case values? I thought this was a compile error.

I slightly mis-spoke. I meant if you take a current valid switch statement, then that switch statement is semantically equivilent to the above pattern, and if you take something in the patten above that fits switch's current "unique and known at compile-time" restrictions, then that's equivilant to a certain switch statement. I guess what I was really saying is that the "unique" requirement makes sense when the values are all known at compile-time, because it's amounts to this... if(z == 1) { ... } else if(z == 1) { /+ dead code +/ } ...but when they're not known at compile-time, that reasoning (along with the resulting restriction) is no longer applicable. Note though, that I'm not necissarily advocating the removal of that restriction from known-at-compile-time values, just for values known only at runtime.
Dec 05 2009
prev sibling parent div0 <div0 users.sourceforge.net> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Sean Kelly wrote:
 In fact, it's already semantically equivilent to that, except that x and y 
 are currently required to be known at compile-time.

D allows duplicate case values? I thought this was a compile error.

It does; from the switch spec: ==== Case expressions must all evaluate to distinct values. Const or immutable variables must all have different names. If they share a value, the first case statement with that value gets control. There may not be two or more default statements. ==== Which seems sensible and should apply to the runtime evaluated case statements as well if that gets added. Haven't tested that though to see if that is actually what happens. - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFLGwKaT9LetA9XoXwRAoAJAKDF2NucN7mcZOgPuleV+Q4HosyTkQCgh2GB EL4RJGfZBK/2nC3iM0ySjWw= =L2pb -----END PGP SIGNATURE-----
Dec 05 2009
prev sibling parent reply BCS <none anon.com> writes:
Hello Nick,

 "Sean Kelly" <sean invisibleduck.org> wrote in message
 news:hfelka$rhf$1 digitalmars.com...
 
 Nick Sabalausky Wrote:
 
 I just noticed in D1 that the values for the cases in a switch must
 be
 known
 at compile-time (btw, the docs don't seem somewhat vague on that).
 Is
 this
 also true in D2? If so, I don't suppose we could get that changed
 before
 the
 book? It's a real PITA for dynamic code.

switch( z ) { case x: ... case y: ... } What should this do? Throw an exception perhaps?

int x = 1, y = 1; if(z == x) { ... } else if(z == y) { ... } In fact, it's already semantically equivilent to that, except that x and y are currently required to be known at compile-time.

Just jumping a ways down this rabbit hole... struct S { int i; int opCmp(S s) { return i-- == s.i++; } { S a,b,c,d,e; ... switch(a) { case b: break; case c: break; case d: break; case e: break; } } Oh, boy. What the hack does the above do?
Dec 05 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"BCS" <none anon.com> wrote in message 
news:a6268ffdcb78cc43db75126b3c news.digitalmars.com...
 Just jumping a ways down this rabbit hole...

 struct S { int i; int opCmp(S s) { return i-- == s.i++; }

 {
    S a,b,c,d,e; ...
    switch(a)
    {
        case b: break;
        case c: break;
        case d: break;
        case e: break;
    }
 }

 Oh, boy. What the hack does the above do?

It blatantly abuses operator overloading ;) Start doing stuff like that, and you'll wind up in wonderland even without changing switch.
Dec 05 2009
parent reply BCS <none anon.com> writes:
Hello Nick,

 "BCS" <none anon.com> wrote in message
 news:a6268ffdcb78cc43db75126b3c news.digitalmars.com...
 
 Just jumping a ways down this rabbit hole...
 
 struct S { int i; int opCmp(S s) { return i-- == s.i++; }
 
 {
 S a,b,c,d,e; ...
 switch(a)
 {
 case b: break;
 case c: break;
 case d: break;
 case e: break;
 }
 }
 Oh, boy. What the hack does the above do?
 

that, and you'll wind up in wonderland even without changing switch.

Ok then how about: switch(c) { case getc(): ..... break; case getc(): ..... break; case getc(): ..... break; case getc(): ..... break; case getc(): ..... break; case getc(): ..... break; case getc(): ..... break; } Are you only going to allow pure functions and expressions with no side effects? I'd guess you could try and set down the list of rules that makes this sane but it's not something I'd like to try any time soon.
Dec 05 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"BCS" <none anon.com> wrote in message 
news:a6268ffdcc98cc43ebb9955246 news.digitalmars.com...
 Hello Nick,

 "BCS" <none anon.com> wrote in message
 news:a6268ffdcb78cc43db75126b3c news.digitalmars.com...

 Just jumping a ways down this rabbit hole...

 struct S { int i; int opCmp(S s) { return i-- == s.i++; }

 {
 S a,b,c,d,e; ...
 switch(a)
 {
 case b: break;
 case c: break;
 case d: break;
 case e: break;
 }
 }
 Oh, boy. What the hack does the above do?

that, and you'll wind up in wonderland even without changing switch.

Ok then how about: switch(c) { case getc(): ..... break; case getc(): ..... break; case getc(): ..... break; case getc(): ..... break; case getc(): ..... break; case getc(): ..... break; case getc(): ..... break; }

I think we can reasonably expect run-time-value cases to be checked in order (or at least whenever the optimizer can't guarantee that it won't matter), so that then becomes pretty simple: If the nth character the user enters (up to the number of cases) matches c, then the nth case is executed, and only the first match is used. I'm not sure it would make much sense to use every match. Switch is a selector, not a multiplexer.
 Are you only going to allow pure functions and expressions with no side 
 effects?

That could be worth exploring. But for now, I'd say no.
 I'd guess you could try and set down the list of rules that makes this 
 sane but it's not something I'd like to try any time soon.

The rule is simple: Just translate it to an if-else chain.
Dec 05 2009
parent BCS <none anon.com> writes:
The point I'm trying to make is that a trivial translation to an if else 
chain is not the only realistic choice. What you propose is non trivial and, 
in a few minuets of thinking I've already thought of a number of ways it 
breaks the expected semantics of the classic switch statement (it can end 
up with worse than linear cost for one) and a small slew of potential issues. 
Personably, I don't see the value in it. It sits on an odd kind of place 
where it has a statically defined number of options but they are dynamically 
defined as to what they are. I rather suspect that in most cases both of 
these will be static or dynamic.

I've never had a case where I needed to use the construct you describe and 
I can think of ways to get the same effect without the potential for problems. 
As a result, I think you have set your self a really hard task of arguing 
that it has more advantages than problems.
Dec 05 2009
prev sibling next sibling parent reply Don <nospam nospam.com> writes:
Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be known 
 at compile-time (btw, the docs don't seem somewhat vague on that). Is this 
 also true in D2? If so, I don't suppose we could get that changed before the 
 book? It's a real PITA for dynamic code. 

I actually tested this. I was surprised. In D2, variables are allowed...
Dec 05 2009
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 12/05/2009 09:20 PM, Don wrote:
 Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be
 known at compile-time (btw, the docs don't seem somewhat vague on
 that). Is this also true in D2? If so, I don't suppose we could get
 that changed before the book? It's a real PITA for dynamic code.

I actually tested this. I was surprised. In D2, variables are allowed...

But not dynamic ones It is a surprise though.
Dec 05 2009
next sibling parent reply Don <nospam nospam.com> writes:
Ellery Newcomer wrote:
 On 12/05/2009 09:20 PM, Don wrote:
 Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be
 known at compile-time (btw, the docs don't seem somewhat vague on
 that). Is this also true in D2? If so, I don't suppose we could get
 that changed before the book? It's a real PITA for dynamic code.

I actually tested this. I was surprised. In D2, variables are allowed...

But not dynamic ones It is a surprise though.

Eg, this works: for (int i=0; i<10; ++i) { switch(x) { case 3: break; case i: break; default: } }
Dec 05 2009
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 12/05/2009 11:17 PM, Don wrote:
 Ellery Newcomer wrote:
 On 12/05/2009 09:20 PM, Don wrote:
 Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be
 known at compile-time (btw, the docs don't seem somewhat vague on
 that). Is this also true in D2? If so, I don't suppose we could get
 that changed before the book? It's a real PITA for dynamic code.

I actually tested this. I was surprised. In D2, variables are allowed...

But not dynamic ones It is a surprise though.

Eg, this works: for (int i=0; i<10; ++i) { switch(x) { case 3: break; case i: break; default: } }

Oop. Never mind. I was looking at void main(string[] args){ int i = to!(int)(args[1]); switch(i){ case args.length: writeln("hey!"); } } Now I'm really surprised.
Dec 06 2009
parent Don <nospam nospam.com> writes:
Ellery Newcomer wrote:
 On 12/05/2009 11:17 PM, Don wrote:
 Ellery Newcomer wrote:
 On 12/05/2009 09:20 PM, Don wrote:
 Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be
 known at compile-time (btw, the docs don't seem somewhat vague on
 that). Is this also true in D2? If so, I don't suppose we could get
 that changed before the book? It's a real PITA for dynamic code.

I actually tested this. I was surprised. In D2, variables are allowed...

But not dynamic ones It is a surprise though.

Eg, this works: for (int i=0; i<10; ++i) { switch(x) { case 3: break; case i: break; default: } }

Oop. Never mind. I was looking at void main(string[] args){ int i = to!(int)(args[1]); switch(i){ case args.length: writeln("hey!"); } } Now I'm really surprised.

The spec says: "The case expressions must all evaluate to a constant value or array, or a runtime initialized const or immutable variable of integral type. " But in reality, it seems that the cases can either be int or string symbols or expressions. If they are expressions, they are evaluated at compile time. That's quite nice, as it avoids the downsides which BCS and I had mentioned. Maybe it's too much of a special case though? Seems like yet another Easter egg. Or else it's a bug.
Dec 06 2009
prev sibling parent Don <nospam nospam.com> writes:
Ellery Newcomer wrote:
 On 12/05/2009 09:20 PM, Don wrote:
 Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be
 known at compile-time (btw, the docs don't seem somewhat vague on
 that). Is this also true in D2? If so, I don't suppose we could get
 that changed before the book? It's a real PITA for dynamic code.

I actually tested this. I was surprised. In D2, variables are allowed...

But not dynamic ones It is a surprise though.

It might just be bug 2414.
Dec 05 2009
prev sibling next sibling parent reply downs <default_357-line yahoo.de> writes:
Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be known 
 at compile-time (btw, the docs don't seem somewhat vague on that). Is this 
 also true in D2? If so, I don't suppose we could get that changed before the 
 book? It's a real PITA for dynamic code. 
 
 

I wish they'd get over it. import tools.base; ... mixin( ReplaceConcat!(2, "if (x == #) { ! } else", "#", "!", "A", "handleTheACase; ", "B", "handleTheBCase; ", "C", "handleTheCCase; " ) ~ " assert(false); " );
Dec 07 2009
next sibling parent retard <re tard.com.invalid> writes:
Mon, 07 Dec 2009 16:55:43 +0100, downs wrote:

 Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be
 known at compile-time (btw, the docs don't seem somewhat vague on
 that). Is this also true in D2? If so, I don't suppose we could get
 that changed before the book? It's a real PITA for dynamic code.
 
 
 

import tools.base; ... mixin( ReplaceConcat!(2, "if (x == #) { ! } else", "#", "!", "A", "handleTheACase; ", "B", "handleTheBCase; ", "C", "handleTheCCase; " ) ~ " assert(false); " );

That reminded me.. I should write a case-of mixin some day: auto result = mixin case_of(foo, ` Tree(l,r) => "We have children "~l.toString()~" and "~r.toString() Nil => "It's a leaf" `);
Dec 07 2009
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"downs" <default_357-line yahoo.de> wrote in message 
news:hfj8qb$ps2$1 digitalmars.com...
 Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be 
 known
 at compile-time (btw, the docs don't seem somewhat vague on that). Is 
 this
 also true in D2? If so, I don't suppose we could get that changed before 
 the
 book? It's a real PITA for dynamic code.

I wish they'd get over it. import tools.base; ... mixin( ReplaceConcat!(2, "if (x == #) { ! } else", "#", "!", "A", "handleTheACase; ", "B", "handleTheBCase; ", "C", "handleTheCCase; " ) ~ " assert(false); " );

That's just ugly.
Dec 07 2009
prev sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Mon, 07 Dec 2009 16:55:43 +0100, downs <default_357-line yahoo.de>  
wrote:

 Nick Sabalausky wrote:
 I just noticed in D1 that the values for the cases in a switch must be  
 known
 at compile-time (btw, the docs don't seem somewhat vague on that). Is  
 this
 also true in D2? If so, I don't suppose we could get that changed  
 before the
 book? It's a real PITA for dynamic code.

I wish they'd get over it. import tools.base; ... mixin( ReplaceConcat!(2, "if (x == #) { ! } else", "#", "!", "A", "handleTheACase; ", "B", "handleTheBCase; ", "C", "handleTheCCase; " ) ~ " assert(false); " );

Now if only D templates handled variadic alias parameters, and my idea of mixin templates, we could instead have this syntax: int n; SwitchCase!( n, A, handleA(), B, handleB(), C, handleC(), assert( false ) ); -- Simen
Dec 08 2009
parent BCS <none anon.com> writes:
Hello Simen,

 On Mon, 07 Dec 2009 16:55:43 +0100, downs <default_357-line yahoo.de>
 wrote:
 
 Nick Sabalausky wrote:
 
 I just noticed in D1 that the values for the cases in a switch must
 be
 known
 at compile-time (btw, the docs don't seem somewhat vague on that).
 Is
 this
 also true in D2? If so, I don't suppose we could get that changed
 before the
 book? It's a real PITA for dynamic code.

import tools.base; ... mixin( ReplaceConcat!(2, "if (x == #) { ! } else", "#", "!", "A", "handleTheACase; ", "B", "handleTheBCase; ", "C", "handleTheCCase; " ) ~ " assert(false); " );


I want this (for other reasons).
 and my idea
 of  mixin templates, we could instead have this syntax:
 
 int n;
 SwitchCase!( n,
 A, handleA(),
 B, handleB(),
 C, handleC(),
 assert( false )
 );

I think you ca get this to work right now: SwitchCase!(n). Case!(A, handleA). Case!(B, handleB). Case!(C, handleC). DefaultFail!();
Dec 08 2009
prev sibling parent retard <re tard.com.invalid> writes:
Sat, 05 Dec 2009 20:03:28 -0500, Nick Sabalausky wrote:

 "grauzone" <none example.net> wrote in message
 news:hfeu6p$1apu$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Ellery Newcomer" <ellery-newcomer utulsa.edu> wrote in message
 It's a useful divergence. It's a feature that should exist. But I
 contend it makes more sense to make a new construct which *is*
 equivalent to a certain pattern of nested ifs (switch isn't) and
 incorporate your feature into that than to shoehorn it into switch.

I definitely agree we need a new switch that isn't so stuck in C-land. And if we got it, I'd be perfectly happy to restrict all the new stuff to the newer switch and just let C-style switch atrophy into oblivion. But a new switch just doesn't seem to be happening :(.

You'd still need to keep around the old switch for stuff like Duff's Device. But I agree that it'd be nice to have a new switch for the following reasons: could use pattern matching instead of just a list of values, no redundant "case", no fallthrough by default, allow a more functional programming style.

I have to admit, I'm so jealous of what I've seen of Nemerle's pattern matching (and it's metaprogramming), that I've been tempted to to give a shot at switching to it for things that don't strickly need system-level capabilities.

I sense words of heresy! TBH pattern matching is pretty nice. But given the amount of time we have left before D2 is out, I don't really expect anything to change anymore. D3 might not be ever released if D2 fails. And I somehow can't see the D community embracing the functional programming paradigm.
Dec 08 2009