www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Mixin operator 'if' directly

reply Andrey <saasecondbox yandex.ru> writes:
Hi,
Here is a template mixin:
 mixin template create(alias input, uint index, alias data)
 {
     if(input.length < index) return;
 
     // ... some code
 }
When I try to compile it, I get:
 Error: declaration expected, not if
Is it possible to mixin operator 'if' directly inside my template mixin?
Dec 19 2018
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
Mixin templates don't work on statements only declarations like structs.
Dec 19 2018
prev sibling parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 19 December 2018 at 13:37:17 UTC, Andrey wrote:
 Hi,
 Here is a template mixin:
 mixin template create(alias input, uint index, alias data)
 {
     if(input.length < index) return;
 
     // ... some code
 }
When I try to compile it, I get:
 Error: declaration expected, not if
Is it possible to mixin operator 'if' directly inside my template mixin?
What you want to use is "static if". The correct way to do the above would be this: mixin template create(alias input, uint index, alias data) { static if(input.length >= index) // Reversed the logic. { // ... some code } }
Dec 19 2018
parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 19 December 2018 at 15:09:47 UTC, bauss wrote:
 On Wednesday, 19 December 2018 at 13:37:17 UTC, Andrey wrote:
 Hi,
 Here is a template mixin:
 mixin template create(alias input, uint index, alias data)
 {
     if(input.length < index) return;
 
     // ... some code
 }
When I try to compile it, I get:
 Error: declaration expected, not if
Is it possible to mixin operator 'if' directly inside my template mixin?
What you want to use is "static if". The correct way to do the above would be this: mixin template create(alias input, uint index, alias data) { static if(input.length >= index) // Reversed the logic. { // ... some code } }
That's assuming that it's compile-time data though. If not then you can't do what you want to do. What you can do is wrap it in a function in the mixin template which you just call after instantiating it.
Dec 19 2018
parent reply Neia Neutuladh <neia ikeran.org> writes:
On Wed, 19 Dec 2018 15:12:14 +0000, bauss wrote:
 That's assuming that it's compile-time data though.
 
 If not then you can't do what you want to do.
 
 What you can do is wrap it in a function in the mixin template which you
 just call after instantiating it.
Or while instantiating it: mixin template foo() { int _ignoreme() { if (readln.strip == "abort") throw new AbortException; return 1; } int _alsoIgnoreMe = _ignoreme(); } void main() { mixin foo; }
Dec 19 2018
next sibling parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 19 December 2018 at 15:40:50 UTC, Neia Neutuladh 
wrote:
 On Wed, 19 Dec 2018 15:12:14 +0000, bauss wrote:
 That's assuming that it's compile-time data though.
 
 If not then you can't do what you want to do.
 
 What you can do is wrap it in a function in the mixin template 
 which you just call after instantiating it.
Or while instantiating it: mixin template foo() { int _ignoreme() { if (readln.strip == "abort") throw new AbortException; return 1; } int _alsoIgnoreMe = _ignoreme(); } void main() { mixin foo; }
That's a genius hack. I have to adapt this!
Dec 20 2018
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Dec 20, 2018 at 11:04:19AM +0000, bauss via Digitalmars-d-learn wrote:
 On Wednesday, 19 December 2018 at 15:40:50 UTC, Neia Neutuladh wrote:
[...]
 mixin template foo()
 {
   int _ignoreme()
   {
     if (readln.strip == "abort") throw new AbortException;
     return 1;
   }
   int _alsoIgnoreMe = _ignoreme();
 }
 void main()
 {
   mixin foo;
 }
That's a genius hack. I have to adapt this!
Me too! This is awesome! This basically lets you insert arbitrary code via mixin templates with essentially no restrictions! You can even reuse the same ignore-identifiers in multiple instantiations of the same template, e.g.: import std.stdio; mixin template CodeMixin(int i) { int _impl() { static if (i == 0) { writeln("Haha, we inserted code via declarations!"); return int.init; } else static if (i == 1) { writeln("Well whaddya know, we can do multiple mixins!"); return int.init; } else static assert(0); } int _impl2 = _impl(); } void main() { writeln("Does it respect order?"); mixin CodeMixin!0; writeln("I should think so! But you never know..."); mixin CodeMixin!1; writeln("Wow, can we really do multiple mixins of this sort?"); } The output is: Does it respect order? Haha, we inserted code via declarations! I should think so! But you never know... Well whaddya know, we can do multiple mixins! Wow, can we really do multiple mixins of this sort? T -- If I were two-faced, would I be wearing this one? -- Abraham Lincoln
Dec 20 2018
next sibling parent bauss <jj_1337 live.dk> writes:
On Thursday, 20 December 2018 at 16:23:39 UTC, H. S. Teoh wrote:
 On Thu, Dec 20, 2018 at 11:04:19AM +0000, bauss via 
 Digitalmars-d-learn wrote:
 [...]
[...]
 [...]
Me too! This is awesome! This basically lets you insert arbitrary code via mixin templates with essentially no restrictions! You can even reuse the same ignore-identifiers in multiple instantiations of the same template, e.g.: [...]
I have so many places where I created a function manually using mixin template, that I then call afterwards. I can save so many manual function calls, allowing for easier maintenance! I have no idea why I've never thought about that before.
Dec 20 2018
prev sibling parent Michelle Long <HappyDance321 gmail.com> writes:
On Thursday, 20 December 2018 at 16:23:39 UTC, H. S. Teoh wrote:
 On Thu, Dec 20, 2018 at 11:04:19AM +0000, bauss via 
 Digitalmars-d-learn wrote:
 On Wednesday, 19 December 2018 at 15:40:50 UTC, Neia Neutuladh 
 wrote:
[...]
 mixin template foo()
 {
   int _ignoreme()
   {
     if (readln.strip == "abort") throw new AbortException;
     return 1;
   }
   int _alsoIgnoreMe = _ignoreme();
 }
 void main()
 {
   mixin foo;
 }
That's a genius hack. I have to adapt this!
Me too! This is awesome! This basically lets you insert arbitrary code via mixin templates with essentially no restrictions! You can even reuse the same ignore-identifiers in multiple instantiations of the same template, e.g.: import std.stdio; mixin template CodeMixin(int i) { int _impl() { static if (i == 0) { writeln("Haha, we inserted code via declarations!"); return int.init; } else static if (i == 1) { writeln("Well whaddya know, we can do multiple mixins!"); return int.init; } else static assert(0); } int _impl2 = _impl(); } void main() { writeln("Does it respect order?"); mixin CodeMixin!0; writeln("I should think so! But you never know..."); mixin CodeMixin!1; writeln("Wow, can we really do multiple mixins of this sort?"); } The output is: Does it respect order? Haha, we inserted code via declarations! I should think so! But you never know... Well whaddya know, we can do multiple mixins! Wow, can we really do multiple mixins of this sort? T
Note that it even captures locals: import std.stdio, std.conv; mixin template CodeMixin(int i) { int _impl() { static if (i == 0) { writeln("Haha, we inserted code via declarations! - " ~ to!string(x)); return int.init; } else static if (i == 1) { writeln("Well whaddya know, we can do multiple mixins! - " ~ to!string(x)); return int.init; } else static assert(0); } int _impl2 = _impl(); } void main() { int x = 3; writeln("Does it respect order?"); mixin CodeMixin!0; writeln("I should think so! But you never know..."); x = 4; mixin CodeMixin!1; writeln("Wow, can we really do multiple mixins of this sort?"); getchar(); } Seems like it could be used to replace a lot of string mixins so that real debugging could take place along with CT error checking, etc.
Dec 21 2018
prev sibling parent reply Timoses <timosesu gmail.com> writes:
On Wednesday, 19 December 2018 at 15:40:50 UTC, Neia Neutuladh 
wrote:
 On Wed, 19 Dec 2018 15:12:14 +0000, bauss wrote:
 Or while instantiating it:

 mixin template foo()
 {
   int _ignoreme()
   {
     if (readln.strip == "abort") throw new AbortException;
     return 1;
   }
   int _alsoIgnoreMe = _ignoreme();
 }
 void main()
 {
   mixin foo;
 }
Awesome hack! Being a hack, it would be even nicer if it worked ouf of the box: mixin template foo(bool b) { int _impl() { writeln(b); return int.init; } int _ipml2 = _impl(); } vs mixin template foo(bool b) { writeln(b); }
Dec 21 2018
next sibling parent Michelle Long <HappyDance321 gmail.com> writes:
On Saturday, 22 December 2018 at 03:44:09 UTC, Timoses wrote:
 On Wednesday, 19 December 2018 at 15:40:50 UTC, Neia Neutuladh 
 wrote:
 On Wed, 19 Dec 2018 15:12:14 +0000, bauss wrote:
 Or while instantiating it:

 mixin template foo()
 {
   int _ignoreme()
   {
     if (readln.strip == "abort") throw new AbortException;
     return 1;
   }
   int _alsoIgnoreMe = _ignoreme();
 }
 void main()
 {
   mixin foo;
 }
Awesome hack! Being a hack, it would be even nicer if it worked ouf of the box: mixin template foo(bool b) { int _impl() { writeln(b); return int.init; } int _ipml2 = _impl(); } vs mixin template foo(bool b) { writeln(b); }
Yep, except they will probably disable it in some way. Surely though a template could be created that does all the work. Just pass an lambda in to a template. mixin template Code(alias f) { int _impl2 = (() { f(); return int.init; })(); } mixin Code!(() { writeln("Haha, we inserted code via declarations!");}); So now you can do mixin template foo(bool b) { mixin Code!(() { writeln(b); }); } If it could be made robust, maybe it would be effective. One still can't insert arbitrary code though. So it is not as useful as it looks but still gets over the arbitrary restriction.
Dec 21 2018
prev sibling next sibling parent Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Saturday, 22 December 2018 at 03:44:09 UTC, Timoses wrote:
 On Wednesday, 19 December 2018 at 15:40:50 UTC, Neia Neutuladh 
 wrote:
 On Wed, 19 Dec 2018 15:12:14 +0000, bauss wrote:
 Or while instantiating it:

 mixin template foo()
 {
   int _ignoreme()
   {
     if (readln.strip == "abort") throw new AbortException;
     return 1;
   }
   int _alsoIgnoreMe = _ignoreme();
 }
 void main()
 {
   mixin foo;
 }
Awesome hack! Being a hack, it would be even nicer if it worked ouf of the box: mixin template foo(bool b) { int _impl() { writeln(b); return int.init; } int _ipml2 = _impl(); } vs mixin template foo(bool b) { writeln(b); }
https://issues.dlang.org/show_bug.cgi?id=19506
Dec 22 2018
prev sibling parent reply bauss <jj_1337 live.dk> writes:
On Saturday, 22 December 2018 at 03:44:09 UTC, Timoses wrote:
 Awesome hack!
 Being a hack, it would be even nicer if it worked ouf of the 
 box:

     mixin template foo(bool b)
     {
         int _impl() { writeln(b); return int.init; }
         int _ipml2 = _impl();
     }

 vs

     mixin template foo(bool b)
     {
         writeln(b);
     }
I think this is the closest we can come to it: mixin template Execute(alias p) { auto __execute__() { p(); return 0; } auto __unused__ = __execute__(); } mixin template MyTemplate(int a) { mixin Execute!({ import std.stdio : writeln; writeln(a); }); } void main() { mixin MyTemplate!10; }
Dec 22 2018
parent Basile B. <b2.temp gmx.com> writes:
On Saturday, 22 December 2018 at 10:11:23 UTC, bauss wrote:
 On Saturday, 22 December 2018 at 03:44:09 UTC, Timoses wrote:
 Awesome hack!
 Being a hack, it would be even nicer if it worked ouf of the 
 box:

     mixin template foo(bool b)
     {
         int _impl() { writeln(b); return int.init; }
         int _ipml2 = _impl();
     }

 vs

     mixin template foo(bool b)
     {
         writeln(b);
     }
I think this is the closest we can come to it: mixin template Execute(alias p) { auto __execute__() { p(); return 0; } auto __unused__ = __execute__(); } mixin template MyTemplate(int a) { mixin Execute!({ import std.stdio : writeln; writeln(a); }); } void main() { mixin MyTemplate!10; }
One more line can be saved using a lambda to wrap the alias: template ExpressionStatement(alias p) { const __unused__ = {p(); return 0;}(); } Also i prefer the name `ExpressionStatement` to `Execute` because this describes exactly what the template does and define its limits at the same time. And congrats to Neia Neutuladh for this find.
Dec 22 2018