Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
November 13, 2010 Switch constants | ||||
---|---|---|---|---|
| ||||
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 |
November 13, 2010 Re: Switch constants | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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? > Well, there is fall-through ;) And there still could be goto's. 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 |
November 13, 2010 Re: Switch constants | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | "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? |
November 14, 2010 Re: Switch constants | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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.
|
November 14, 2010 Re: Switch constants | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Murphy | 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
|
November 14, 2010 Re: Switch constants | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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;
}
}
|
Copyright © 1999-2021 by the D Language Foundation