digitalmars.D - [Article Submission] Have Your Efficiency, and Flexibility Too
- Nick Sabalausky (3/3) May 30 2011 Getting in just under the wire here. I seem to have misjudged the scope ...
- Lars T. Kyllingstad (22/26) May 31 2011 Nice article. :) Some of the code snippets were a bit on the longish
- Nick Sabalausky (4/29) May 31 2011 Thanks :)
- bearophile (46/47) May 31 2011 Regarding your addGizmos() in ex6_meta_flex3_runtimeToCompileTime1.d:
- Timon Gehr (28/42) May 31 2011 Nice, but isSpinnable is always checked twice with your approach. Better...
- Nick Sabalausky (11/29) May 31 2011 Thanks :)
- Timon Gehr (22/58) May 31 2011 Okay. Valid point. It is true that making the article more complicated i...
- Nick Sabalausky (10/81) May 31 2011 Hmm, something screwey seems to be going on. Your test example works for...
- Nick Sabalausky (13/51) May 31 2011 I think typeof(this) just seems to be screwy. Check this out:
- Steven Schveighoffer (6/63) Jun 01 2011 I think there are certain special situations where you can use
- Timon Gehr (12/17) Jun 01 2011 It is not documented in detail but it is there =).
- Steven Schveighoffer (5/28) Jun 01 2011 I agree with all of this, I think it should work, judging from that
- Nick Sabalausky (4/18) Jun 01 2011 Done:
- Nick Sabalausky (7/35) May 31 2011 I love this idea. I had no idea you could use TypeTuple for values. But ...
- Timon Gehr (4/43) May 31 2011 Interesting. I suspect that is a bug. Can somebody shed light on what th...
- bearophile (4/6) May 31 2011 Are you able to reduce this to a minimal test case?
- Nick Sabalausky (6/10) May 31 2011 If it is indeed a bug then I'll try. But the fact that there's an error
- Timon Gehr (43/56) Jun 01 2011 'np' is just an integer literal at the point of instantiation. Would you...
- Ary Manzana (3/50) May 31 2011 Why you need a type tuple? Can't you do:
- Timon Gehr (6/8) May 31 2011 That is a runtime foreach, so no. If the argument is a TypeTuple, the co...
- bearophile (6/8) May 31 2011 See:
- Timon Gehr (45/53) May 31 2011 Nope. You don't get a guarantee from the language that your code will be...
- Nick Sabalausky (5/8) May 31 2011 Thanks everyone for all the great suggestions. With 10 minutes now until...
Getting in just under the wire here. I seem to have misjudged the scope of my topic, it ended up a bit large... Anyway, here's my entry: http://www.semitwist.com/articles/EfficientAndFlexible/SinglePage/
May 30 2011
On Tue, 31 May 2011 02:36:58 -0400, Nick Sabalausky wrote:Getting in just under the wire here. I seem to have misjudged the scope of my topic, it ended up a bit large... Anyway, here's my entry: http://www.semitwist.com/articles/EfficientAndFlexible/SinglePage/Nice article. :) Some of the code snippets were a bit on the longish side, but I can't really say how they could be reduced. The narrative is a nice touch. May I make two small suggestions regarding the ex5_meta_deadDuck1.d snippet? Firstly, I cringe whenever I see is(typeof((){...})) being used to test whether something compiles or not. I'd much prefer immutable bool isIGizmo = __traits(compiles, { ... }); Granted, __traits() is pretty ugly too, but at least you have the "compiles" directive making it clear what's going on. Secondly, you could replace the immutable(void[0]) member with an enum, which also doesn't take up any space. I find enum _this_implements_interface_IGizmo_ = true; a lot more descriptive of its purpose. Then you could also replace the "auto dummy = T._this_implements..." line with static assert (T._this_implements_interface_IGizmo_); which will fail if _this_implements... isn't declared or if it's declared to be false. -Lars
May 31 2011
"Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> wrote in message news:is2aah$29pf$1 digitalmars.com...On Tue, 31 May 2011 02:36:58 -0400, Nick Sabalausky wrote:Thanks :)Getting in just under the wire here. I seem to have misjudged the scope of my topic, it ended up a bit large... Anyway, here's my entry: http://www.semitwist.com/articles/EfficientAndFlexible/SinglePage/Nice article. :) Some of the code snippets were a bit on the longish side, but I can't really say how they could be reduced. The narrative is a nice touch.May I make two small suggestions regarding the ex5_meta_deadDuck1.d snippet? Firstly, I cringe whenever I see is(typeof((){...})) being used to test whether something compiles or not. I'd much prefer immutable bool isIGizmo = __traits(compiles, { ... }); Granted, __traits() is pretty ugly too, but at least you have the "compiles" directive making it clear what's going on. Secondly, you could replace the immutable(void[0]) member with an enum, which also doesn't take up any space. I find enum _this_implements_interface_IGizmo_ = true; a lot more descriptive of its purpose. Then you could also replace the "auto dummy = T._this_implements..." line with static assert (T._this_implements_interface_IGizmo_); which will fail if _this_implements... isn't declared or if it's declared to be false.All good points.
May 31 2011
Nick Sabalausky:http://www.semitwist.com/articles/EfficientAndFlexible/SinglePage/Regarding your addGizmos() in ex6_meta_flex3_runtimeToCompileTime1.d: void addGizmos(int numPorts, bool isSpinnable, int numGizmos) { // Dispatch to correct version of addGizmosTo. // Effectively converts a runtime value to compile-time. if (numPorts == 1) { if (isSpinnable) addGizmosTo!(1, true )(numGizmos); else addGizmosTo!(1, false)(numGizmos); } else if (numPorts == 2) { if (isSpinnable) addGizmosTo!(2, true )(numGizmos); else addGizmosTo!(2, false)(numGizmos); } else if (numPorts == 3) { if (isSpinnable) addGizmosTo!(3, true )(numGizmos); else addGizmosTo!(3, false)(numGizmos); } else if (numPorts == 5) { if (isSpinnable) addGizmosTo!(5, true )(numGizmos); else addGizmosTo!(5, false)(numGizmos); } else if (numPorts == 10) { if (isSpinnable) addGizmosTo!(10, true )(numGizmos); else addGizmosTo!(10, false)(numGizmos); } else throw new Exception(to!string(numPorts)~"-port Gizmo not supported."); } A shorter way to write it: void addGizmos(int numPorts, bool isSpinnable, int numGizmos) { foreach (np; TypeTuple!(1, 2, 3, 5, 10)) if (numPorts == np) { foreach (b; TypeTuple!(true, false)) if (isSpinnable == b) addGizmosTo!(np, b)(numGizmos); return; } throw new Exception(text(numPorts) ~ "-port Gizmo not supported."); } Bye, bearophile
May 31 2011
bearophile wrote:... A shorter way to write it: void addGizmos(int numPorts, bool isSpinnable, int numGizmos) { foreach (np; TypeTuple!(1, 2, 3, 5, 10)) if (numPorts == np) { foreach (b; TypeTuple!(true, false)) if (isSpinnable == b) addGizmosTo!(np, b)(numGizmos); return; } throw new Exception(text(numPorts) ~ "-port Gizmo not supported."); } Bye, bearophileNice, but isSpinnable is always checked twice with your approach. Better: void addGizmos(int numPorts, bool isSpinnable, int numGizmos) { foreach (np; TypeTuple!(1, 2, 3, 5, 10)) if (numPorts == np) { if (isSpinnable) addGizmosTo!(np, true)(numGizmos); else addGizmosTo!(np, false)(numGizmos); return; } throw new Exception(text(numPorts) ~ "-port Gizmo not supported."); } Article: A very good read, it does not get boring even though it is quite long. I like it. Small nitpick: mixin(declareInterface("IGizmo", "Gizmo!(numPorts, isSpinnable)")); It seems like this should be a mixin template, not a string mixin. Also you wouldn't normally want to specify ThisType. Use typeof(this): mixin template declareInterface(string interfaceName){ mixin(`enum _this_implements_interface_`~interfaceName~`=true;`); mixin(`static assert( is`~interfaceName~`!(typeof(this)), "This type fails to implement `~interfaceName~`" );` ); } and then you do just: mixin declareInterface!"IGizmo"; Timon
May 31 2011
"Timon Gehr" <timon.gehr gmx.ch> wrote in message news:is2lts$2fcn$1 digitalmars.com...Article: A very good read, it does not get boring even though it is quite long. I like it.Thanks :)Small nitpick: mixin(declareInterface("IGizmo", "Gizmo!(numPorts, isSpinnable)")); It seems like this should be a mixin template, not a string mixin. Also you wouldn't normally want to specify ThisType. Use typeof(this): mixin template declareInterface(string interfaceName){ mixin(`enum _this_implements_interface_`~interfaceName~`=true;`); mixin(`static assert( is`~interfaceName~`!(typeof(this)), "This type fails to implement `~interfaceName~`" );` ); } and then you do just: mixin declareInterface!"IGizmo";I like the idea, but I just tried it and when I do that, 'isIGizmo' doesn't seem to be able to find the '_this_implements_interface_IGizmo' (using DMD 2.053). But, I wonder if that approach might be getting a little too fancy for this anyway. That would definitely be the right way to go for a real library, but for the article, the simpler it is to understand how it works, the better, and putting string mixins inside a template mixin is more to understand than just a string mixin (of course, I'm using CTFE too, but that's probably conceptually simpler for most people than template mixins).
May 31 2011
Nick Sabalausky wrote:"Timon Gehr" <timon.gehr gmx.ch> wrote in message news:is2lts$2fcn$1 digitalmars.com...Okay. Valid point. It is true that making the article more complicated is not really an option. But you might want to add a comment that for serious work, template mixins would be better suited (otherwise people will almost certainly copy the string mixin approach ;)) It works for me. Are you sure you did not accidentally break some other part of your __traits(compiles,...) ? My minimal test case: template isIGizmo(T){enum isIGizmo=__traits(compiles,{static assert(T._this_implements_interface_IGizmo);});} mixin template declareInterface(string interfaceName){ mixin(`enum _this_implements_interface_`~interfaceName~`=true;`); mixin(`static assert( is`~interfaceName~`!(typeof(this)), "This type fails to implement `~interfaceName~`" );` ); } struct Gizmo{mixin declareInterface!"IGizmo";} static assert(isIGizmo!Gizmo); void main(){} TimonArticle: A very good read, it does not get boring even though it is quite long. I like it.Thanks :)Small nitpick: mixin(declareInterface("IGizmo", "Gizmo!(numPorts, isSpinnable)")); It seems like this should be a mixin template, not a string mixin. Also you wouldn't normally want to specify ThisType. Use typeof(this): mixin template declareInterface(string interfaceName){ mixin(`enum _this_implements_interface_`~interfaceName~`=true;`); mixin(`static assert( is`~interfaceName~`!(typeof(this)), "This type fails to implement `~interfaceName~`" );` ); } and then you do just: mixin declareInterface!"IGizmo";I like the idea, but I just tried it and when I do that, 'isIGizmo' doesn't seem to be able to find the '_this_implements_interface_IGizmo' (using DMD 2.053). But, I wonder if that approach might be getting a little too fancy for this anyway. That would definitely be the right way to go for a real library, but for the article, the simpler it is to understand how it works, the better, and putting string mixins inside a template mixin is more to understand than just a string mixin (of course, I'm using CTFE too, but that's probably conceptually simpler for most people than template mixins).
May 31 2011
"Timon Gehr" <timon.gehr gmx.ch> wrote in message news:is3rb5$1g32$1 digitalmars.com...Nick Sabalausky wrote:Hmm, something screwey seems to be going on. Your test example works for me too, but I could swear I've checked and double-checked everything (including the "__traits(compiles,...)") , and made your test case and my example as close to each other as I can, and I still can't seem to narrow down what's different. I do know this: In my code, I can't use typeof(this) because the compiler complains that "this" is only valid inside a member function. I have no idea why doing that seems to work, even for me, in your test case."Timon Gehr" <timon.gehr gmx.ch> wrote in message news:is2lts$2fcn$1 digitalmars.com...Okay. Valid point. It is true that making the article more complicated is not really an option. But you might want to add a comment that for serious work, template mixins would be better suited (otherwise people will almost certainly copy the string mixin approach ;)) It works for me. Are you sure you did not accidentally break some other part of your __traits(compiles,...) ? My minimal test case: template isIGizmo(T){enum isIGizmo=__traits(compiles,{static assert(T._this_implements_interface_IGizmo);});} mixin template declareInterface(string interfaceName){ mixin(`enum _this_implements_interface_`~interfaceName~`=true;`); mixin(`static assert( is`~interfaceName~`!(typeof(this)), "This type fails to implement `~interfaceName~`" );` ); } struct Gizmo{mixin declareInterface!"IGizmo";} static assert(isIGizmo!Gizmo); void main(){}Article: A very good read, it does not get boring even though it is quite long. I like it.Thanks :)Small nitpick: mixin(declareInterface("IGizmo", "Gizmo!(numPorts, isSpinnable)")); It seems like this should be a mixin template, not a string mixin. Also you wouldn't normally want to specify ThisType. Use typeof(this): mixin template declareInterface(string interfaceName){ mixin(`enum _this_implements_interface_`~interfaceName~`=true;`); mixin(`static assert( is`~interfaceName~`!(typeof(this)), "This type fails to implement `~interfaceName~`" );` ); } and then you do just: mixin declareInterface!"IGizmo";I like the idea, but I just tried it and when I do that, 'isIGizmo' doesn't seem to be able to find the '_this_implements_interface_IGizmo' (using DMD 2.053). But, I wonder if that approach might be getting a little too fancy for this anyway. That would definitely be the right way to go for a real library, but for the article, the simpler it is to understand how it works, the better, and putting string mixins inside a template mixin is more to understand than just a string mixin (of course, I'm using CTFE too, but that's probably conceptually simpler for most people than template mixins).
May 31 2011
"Nick Sabalausky" <a a.a> wrote in message news:is3tk5$1j2n$1 digitalmars.com..."Timon Gehr" <timon.gehr gmx.ch> wrote in message news:is3rb5$1g32$1 digitalmars.com...I think typeof(this) just seems to be screwy. Check this out: struct Gizmo { static assert( is(typeof(this)==Gizmo) ); } void main() {} Error: static assert (is(typeof(__error) == Gizmo)) is false But this is fine: struct Gizmo { alias typeof(this) Foo; typeof(this)* ptr; }It works for me. Are you sure you did not accidentally break some other part of your __traits(compiles,...) ? My minimal test case: template isIGizmo(T){enum isIGizmo=__traits(compiles,{static assert(T._this_implements_interface_IGizmo);});} mixin template declareInterface(string interfaceName){ mixin(`enum _this_implements_interface_`~interfaceName~`=true;`); mixin(`static assert( is`~interfaceName~`!(typeof(this)), "This type fails to implement `~interfaceName~`" );` ); } struct Gizmo{mixin declareInterface!"IGizmo";} static assert(isIGizmo!Gizmo); void main(){}Hmm, something screwey seems to be going on. Your test example works for me too, but I could swear I've checked and double-checked everything (including the "__traits(compiles,...)") , and made your test case and my example as close to each other as I can, and I still can't seem to narrow down what's different. I do know this: In my code, I can't use typeof(this) because the compiler complains that "this" is only valid inside a member function. I have no idea why doing that seems to work, even for me, in your test case.
May 31 2011
On Tue, 31 May 2011 19:32:59 -0400, Nick Sabalausky <a a.a> wrote:"Nick Sabalausky" <a a.a> wrote in message news:is3tk5$1j2n$1 digitalmars.com...I think there are certain special situations where you can use typeof(this). For example, as the return type for a static method. *looks for doc* Couldn't find any documentation on it... It's somewhat like static this, which is inflexible in how you write it. -Steve"Timon Gehr" <timon.gehr gmx.ch> wrote in message news:is3rb5$1g32$1 digitalmars.com...I think typeof(this) just seems to be screwy. Check this out: struct Gizmo { static assert( is(typeof(this)==Gizmo) ); } void main() {} Error: static assert (is(typeof(__error) == Gizmo)) is false But this is fine: struct Gizmo { alias typeof(this) Foo; typeof(this)* ptr; }It works for me. Are you sure you did not accidentally break some other part of your __traits(compiles,...) ? My minimal test case: template isIGizmo(T){enum isIGizmo=__traits(compiles,{static assert(T._this_implements_interface_IGizmo);});} mixin template declareInterface(string interfaceName){ mixin(`enum _this_implements_interface_`~interfaceName~`=true;`); mixin(`static assert( is`~interfaceName~`!(typeof(this)), "This type fails to implement `~interfaceName~`" );` ); } struct Gizmo{mixin declareInterface!"IGizmo";} static assert(isIGizmo!Gizmo); void main(){}Hmm, something screwey seems to be going on. Your test example works for me too, but I could swear I've checked and double-checked everything (including the "__traits(compiles,...)") , and made your test case and my example as close to each other as I can, and I still can't seem to narrow down what's different. I do know this: In my code, I can't use typeof(this) because the compiler complains that "this" is only valid inside a member function. I have no idea why doing that seems to work, even for me, in your test case.
Jun 01 2011
Steven Schveighoffer wrote:I think there are certain special situations where you can use typeof(this). For example, as the return type for a static method. *looks for doc* Couldn't find any documentation on it... It's somewhat like static this, which is inflexible in how you write it. -SteveIt is not documented in detail but it is there =). See: http://www.digitalmars.com/d/2.0/declaration.html "1. typeof(this) will generate the type of what this would be in a non-static member function, even if not in a member function. " Therefore it is not special cased, but is supposed to work universally. That it does not work for Nick is probably a bug, not a sensible and thought-out limitation. It can be very handy for Metaprogramming, this needs to get fixed at some point. Nick: Can you try to deduce a minimal test case? (Or provide the full listing of the code?) Timon
Jun 01 2011
On Wed, 01 Jun 2011 10:32:10 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:Steven Schveighoffer wrote:D'oh! I must have skipped over that page.I think there are certain special situations where you can use typeof(this). For example, as the return type for a static method. *looks for doc* Couldn't find any documentation on it... It's somewhat like static this, which is inflexible in how you write it. -SteveIt is not documented in detail but it is there =). See: http://www.digitalmars.com/d/2.0/declaration.html "1. typeof(this) will generate the type of what this would be in a non-static member function, even if not in a member function. "Therefore it is not special cased, but is supposed to work universally. That it does not work for Nick is probably a bug, not a sensible and thought-out limitation. It can be very handy for Metaprogramming, this needs to get fixed at some point. Nick: Can you try to deduce a minimal test case? (Or provide the full listing of the code?)I agree with all of this, I think it should work, judging from that documentation. -Steve
Jun 01 2011
"Timon Gehr" <timon.gehr gmx.ch> wrote in message news:is5iha$1e2k$1 digitalmars.com...It is not documented in detail but it is there =). See: http://www.digitalmars.com/d/2.0/declaration.html "1. typeof(this) will generate the type of what this would be in a non-static member function, even if not in a member function. " Therefore it is not special cased, but is supposed to work universally. That it does not work for Nick is probably a bug, not a sensible and thought-out limitation. It can be very handy for Metaprogramming, this needs to get fixed at some point. Nick: Can you try to deduce a minimal test case? (Or provide the full listing of the code?)Done: http://d.puremagic.com/issues/show_bug.cgi?id=6087
Jun 01 2011
"Timon Gehr" <timon.gehr gmx.ch> wrote in message news:is2lts$2fcn$1 digitalmars.com...bearophile wrote:I love this idea. I had no idea you could use TypeTuple for values. But it doesn't seem to be working in ths particular case. On the line that tries to call 'addGizmosTo' I get this compiler error: Error: template instance cannot use local 'np' as parameter to non-global template addGizmosTo(int numPorts,bool isSpinnable)... A shorter way to write it: void addGizmos(int numPorts, bool isSpinnable, int numGizmos) { foreach (np; TypeTuple!(1, 2, 3, 5, 10)) if (numPorts == np) { foreach (b; TypeTuple!(true, false)) if (isSpinnable == b) addGizmosTo!(np, b)(numGizmos); return; } throw new Exception(text(numPorts) ~ "-port Gizmo not supported."); } Bye, bearophileNice, but isSpinnable is always checked twice with your approach. Better: void addGizmos(int numPorts, bool isSpinnable, int numGizmos) { foreach (np; TypeTuple!(1, 2, 3, 5, 10)) if (numPorts == np) { if (isSpinnable) addGizmosTo!(np, true)(numGizmos); else addGizmosTo!(np, false)(numGizmos); return; } throw new Exception(text(numPorts) ~ "-port Gizmo not supported."); }
May 31 2011
Nick Sabalausky wrote:"Timon Gehr" <timon.gehr gmx.ch> wrote in message news:is2lts$2fcn$1 digitalmars.com...Interesting. I suspect that is a bug. Can somebody shed light on what the purpose of that Error message is? Timonbearophile wrote:I love this idea. I had no idea you could use TypeTuple for values. But it doesn't seem to be working in ths particular case. On the line that tries to call 'addGizmosTo' I get this compiler error: Error: template instance cannot use local 'np' as parameter to non-global template addGizmosTo(int numPorts,bool isSpinnable)... A shorter way to write it: void addGizmos(int numPorts, bool isSpinnable, int numGizmos) { foreach (np; TypeTuple!(1, 2, 3, 5, 10)) if (numPorts == np) { foreach (b; TypeTuple!(true, false)) if (isSpinnable == b) addGizmosTo!(np, b)(numGizmos); return; } throw new Exception(text(numPorts) ~ "-port Gizmo not supported."); } Bye, bearophileNice, but isSpinnable is always checked twice with your approach. Better: void addGizmos(int numPorts, bool isSpinnable, int numGizmos) { foreach (np; TypeTuple!(1, 2, 3, 5, 10)) if (numPorts == np) { if (isSpinnable) addGizmosTo!(np, true)(numGizmos); else addGizmosTo!(np, false)(numGizmos); return; } throw new Exception(text(numPorts) ~ "-port Gizmo not supported."); }
May 31 2011
Nick Sabalausky:Error: template instance cannot use local 'np' as parameter to non-global template addGizmosTo(int numPorts,bool isSpinnable)Are you able to reduce this to a minimal test case? Bye, bearophile
May 31 2011
"bearophile" <bearophileHUGS lycos.com> wrote in message news:is45u7$21vq$1 digitalmars.com...Nick Sabalausky:If it is indeed a bug then I'll try. But the fact that there's an error message for it seems to indicate this is intended for some reason. After all, addGizmosTo *is* a non-global template, just like the message says. And 'np' shouldn't be visible outside the function it's in, ie, it's local.Error: template instance cannot use local 'np' as parameter to non-global template addGizmosTo(int numPorts,bool isSpinnable)Are you able to reduce this to a minimal test case?
May 31 2011
Nick Sabalausky wrote:"bearophile" <bearophileHUGS lycos.com> wrote in message news:is45u7$21vq$1 digitalmars.com...'np' is just an integer literal at the point of instantiation. Would you want to not be able to call a function with local variables as parameters either? Eg: int main(){ int foo(int){...} foreach(np;[1,2,3,4,5]) foo(np); } If the bug was there for runtime foreach too, this would print Error: function call cannot use local 'np' as parameter to non-global function foo. This would also be a fit for It is certainly a bug, there is no reason why it should not work. (an integer literal is not bound to a scope). Minimal test case: import std.typetuple; void main(){ int foo(int x)(){return x;} foreach(i;TypeTuple!(0)) foo!(i); } Bug report: http://d.puremagic.com/issues/show_bug.cgi?id=6084 Probably, the Error is intended for the following case: int bar(int x)(){return x;} void main(){ immutable int i=0; int foo(int x)(){return x;} foo!i; //error bar!i; //ok } Is there any reason why this should not work? Is it just an implementation issue? (I have heard of immutable compile-time values not yet working properly.) Workaround for the bug: import std.typetuple; void main(){ int foo(int x)(){return x;} foreach(_i;TypeTuple!(0)){ enum i=_i; foo!i; } } I think it should be possible to fix it for TypeTuple foreach by having the iteration variable be enum. I'll have a look at the compiler. TimonNick Sabalausky:If it is indeed a bug then I'll try. But the fact that there's an error message for it seems to indicate this is intended for some reason. After all, addGizmosTo *is* a non-global template, just like the message says. And 'np' shouldn't be visible outside the function it's in, ie, it's local.Error: template instance cannot use local 'np' as parameter to non-global template addGizmosTo(int numPorts,bool isSpinnable)Are you able to reduce this to a minimal test case?
Jun 01 2011
On 5/31/11 6:05 PM, bearophile wrote:Nick Sabalausky:Why you need a type tuple? Can't you do: foreach(np; [1, 2, 3, 5, 10])http://www.semitwist.com/articles/EfficientAndFlexible/SinglePage/Regarding your addGizmos() in ex6_meta_flex3_runtimeToCompileTime1.d: void addGizmos(int numPorts, bool isSpinnable, int numGizmos) { // Dispatch to correct version of addGizmosTo. // Effectively converts a runtime value to compile-time. if (numPorts == 1) { if (isSpinnable) addGizmosTo!(1, true )(numGizmos); else addGizmosTo!(1, false)(numGizmos); } else if (numPorts == 2) { if (isSpinnable) addGizmosTo!(2, true )(numGizmos); else addGizmosTo!(2, false)(numGizmos); } else if (numPorts == 3) { if (isSpinnable) addGizmosTo!(3, true )(numGizmos); else addGizmosTo!(3, false)(numGizmos); } else if (numPorts == 5) { if (isSpinnable) addGizmosTo!(5, true )(numGizmos); else addGizmosTo!(5, false)(numGizmos); } else if (numPorts == 10) { if (isSpinnable) addGizmosTo!(10, true )(numGizmos); else addGizmosTo!(10, false)(numGizmos); } else throw new Exception(to!string(numPorts)~"-port Gizmo not supported."); } A shorter way to write it: void addGizmos(int numPorts, bool isSpinnable, int numGizmos) { foreach (np; TypeTuple!(1, 2, 3, 5, 10)) if (numPorts == np) { foreach (b; TypeTuple!(true, false)) if (isSpinnable == b) addGizmosTo!(np, b)(numGizmos); return; } throw new Exception(text(numPorts) ~ "-port Gizmo not supported."); } Bye, bearophile
May 31 2011
Ary Manzana wrote:Why you need a type tuple? Can't you do: foreach(np; [1, 2, 3, 5, 10])That is a runtime foreach, so no. If the argument is a TypeTuple, the compiler evaluates the foreach as a "static foreach", effectively duplicating all code in its body and filling in the constants/types in the tuple. I would like an explicit "static foreach" better though. Timon
May 31 2011
Timon Gehr:Nice, but isSpinnable is always checked twice with your approach.Right. But isn't the compiler able to optimize away this inefficiency?I would like an explicit "static foreach" better though.See: http://d.puremagic.com/issues/show_bug.cgi?id=4085 Bye, bearophile
May 31 2011
Timon Gehr:Nope. You don't get a guarantee from the language that your code will be optimized in a certain way. That said, dmd/gdc are _not_ able to do it sensibly for the most trivial case: if(x) writeln("x"); if(!x) writeln("!x"); results in the following when compiled with dmd -O -release -inline. cmp dword ptr [ebp-8], 0 ; first check jz short loc_8096042 ; first check push dword ptr ds:_TMP1+4 push dword ptr ds:_TMP1 call _D3std5stdio16__T7writelnTAyaZ7writelnFAyaZv loc_8096042: cmp dword ptr [ebp-8], 0 ; second check jnz short loc_8096059 ; second check push dword ptr ds:_TMP2+4 push dword ptr ds:_TMP2 call _D3std5stdio16__T7writelnTAyaZ7writelnFAyaZv loc_8096059: ; function epilogue comes here. With gdmd -O -release -inline: mov ecx, [esp+20h+var_4] ; first check test ecx, ecx ; first check jnz short loc_804AE98 ; first check loc_804AE7D: mov [esp+20h+var_20], 2 mov [esp+20h+var_1C], offset unk_80A3448 ;"!x" call _D3std5stdio16__T7writelnTAyaZ7writelnFAyaZv ; function epilogue comes here loc_804AE98: mov [esp+20h+var_20], 1 mov [esp+20h+var_1C], offset asc_80A3446 ; "x" call _D3std5stdio16__T7writelnTAyaZ7writelnFAyaZv mov edx, [esp+20h+var_4] ; second check (nonsense) test edx, edx ; second check (nonsense) jz short loc_804AE7D ; second check (nonsense) ; function epilogue comes here This is _really_ silly oO. gdc was almost there. It clearly had to understand that x and !x are mutually exclusive to generate such code (it _reordered_ the two checks =DD), but then it created 3 totally nonsensical instructions for a totally redundant second check nevertheless. It still gets some credit for duplicating the function epilogue instead of adding another jump. Compilers are not magical, they are stupid programs that cannot replace your insight. ;)Nice, but isSpinnable is always checked twice with your approach.Right. But isn't the compiler able to optimize away this inefficiency?Thanks for the information. I already suspected it to be a matter of implementation. TimonI would like an explicit "static foreach" better though.See: http://d.puremagic.com/issues/show_bug.cgi?id=4085 Bye, bearophile
May 31 2011
"Nick Sabalausky" <a a.a> wrote in message news:is22gk$1v03$1 digitalmars.com...Getting in just under the wire here. I seem to have misjudged the scope of my topic, it ended up a bit large... Anyway, here's my entry: http://www.semitwist.com/articles/EfficientAndFlexible/SinglePage/Thanks everyone for all the great suggestions. With 10 minutes now until midnight GMT, I've incorporated all the changes that I was able to get working.
May 31 2011