digitalmars.D.learn - Switch constants
- bearophile <bearophileHUGS lycos.com> Nov 13 2010
- Dmitry Olshansky <dmitry.olsh gmail.com> Nov 13 2010
- "Daniel Murphy" <yebblies nospamgmail.com> Nov 13 2010
- bearophile <bearophileHUGS lycos.com> Nov 13 2010
- Stanislav Blinov <stanislav.blinov gmail.com> Nov 13 2010
- BCS <anon anon.com> Nov 14 2010
In a not-ranged cases body, like in the program below (that doesn't compile),
the switch variable is a compile-time constant, so why doesn't the compile see
x as constant there?
template Foo(uint x) {
static if (x <= 1)
enum Foo = 1;
else
enum Foo = x * Foo!(x - 1);
}
int bar(uint x) {
switch (x) {
case 0: return Foo!x;
case 1: return Foo!x;
case 2: return Foo!x;
case 3: return Foo!x;
case 4: return Foo!x;
default: return -1;
}
}
void main() {
assert(bar(4) == 24);
}
That code works if I replace lines like:
case 2: return Foo!x;
With:
case 2: return Foo!2;
But when the code isn't DRY bugs may happen...
(There are ten different better ways to write that program, but this is not the
point).
Bye,
bearophile
Nov 13 2010
On 14.11.2010 1:21, bearophile wrote:In a not-ranged cases body, like in the program below (that doesn't compile), the switch variable is a compile-time constant, so why doesn't the compile see x as constant there?
In essence "case x:" is nothing but a glorified local label.template Foo(uint x) { static if (x<= 1) enum Foo = 1; else enum Foo = x * Foo!(x - 1); } int bar(uint x) { switch (x) { case 0: return Foo!x; case 1: return Foo!x; case 2: return Foo!x; case 3: return Foo!x; case 4: return Foo!x; default: return -1; } } void main() { assert(bar(4) == 24); } That code works if I replace lines like: case 2: return Foo!x; With: case 2: return Foo!2; But when the code isn't DRY bugs may happen... (There are ten different better ways to write that program, but this is not the point). Bye, bearophile
-- Dmitry Olshansky
Nov 13 2010
"bearophile" <bearophileHUGS lycos.com> wrote in message news:ibn320$2ucs$1 digitalmars.com...In a not-ranged cases body, like in the program below (that doesn't compile), the switch variable is a compile-time constant, so why doesn't the compile see x as constant there?
In switch statements, you can do stuff like: switch(x) { case 0: case 1: // what is x here? break; } switch(x) { case 0: break; // what is x here? case 1: goto case 0: } goto label1; switch(x) { case 0: label1: break; // what is x here? } switch(x) { case 0: x = y; break; // what is x here? } As far as I know, NONE of the constructs in d allow you to treat a run-time variable as if it was compile-time constant. I doubt this would be possible without flow analysis. You can however do something like this (if you must) template Foo(uint x) { static if (x <= 1) enum Foo = 1; else enum Foo = x * Foo!(x - 1); } int getv(int x) { switch(x) { foreach(i; TypeTuple!(0, 1, 2, 3, 4, 5, 6)) { case i: return Foo!i; } } assert(0); } where the switch expands out to switch(x) { case 0: return Foo!0; case 1: return Foo!1; case 2: return Foo!2; case 3: return Foo!3; case 4: return Foo!4; case 5: return Foo!5; case 6: return Foo!6; } Is this DRY enough for you?
Nov 13 2010
Daniel Murphy:switch(x) { case 0: break; // what is x here? case 1: goto case 0: } etc
You are right. Thank you for all the answers. Bye, bearophile
Nov 13 2010
bearophile wrote:In a not-ranged cases body, like in the program below (that doesn't compile), the switch variable is a compile-time constant, so why doesn't the compile see x as constant there? template Foo(uint x) { static if (x <= 1) enum Foo = 1; else enum Foo = x * Foo!(x - 1); } int bar(uint x) { switch (x) { case 0: return Foo!x; case 1: return Foo!x; case 2: return Foo!x; case 3: return Foo!x; case 4: return Foo!x; default: return -1; } } void main() { assert(bar(4) == 24); } That code works if I replace lines like: case 2: return Foo!x; With: case 2: return Foo!2; But when the code isn't DRY bugs may happen... (There are ten different better ways to write that program, but this is not the point). Bye, bearophile
I would say that while bar may be CTFE'd, it is nevertheless a function that can be called at runtime, in which case x may no longer be a compile-time constant. So there is little compiler can do except for refusing such code.
Nov 13 2010
Hello bearophile,In a not-ranged cases body, like in the program below (that doesn't compile), the switch variable is a compile-time constant, so why doesn't the compile see x as constant there? template Foo(uint x) { static if (x <= 1) enum Foo = 1; else enum Foo = x * Foo!(x - 1); } int bar(uint x) { switch (x) { case 0: return Foo!x; case 1: return Foo!x; case 2: return Foo!x; case 3: return Foo!x; case 4: return Foo!x; default: return -1; } }
If you want exactly that: switch(x) { foreach(X; Tuple!(0,1,2,3,4)) { case X: return Foo!X; } }
Nov 14 2010









Dmitry Olshansky <dmitry.olsh gmail.com> 