www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Request: Auto string mixin templates

reply "JS" <js.mdnq gmail.com> writes:
I have a template t that returns a string that is always to be 
used as a mixin.

It is quite annoying to have to use mixin() on the template.

e.g.,

mixin(t!());

It would be nice to be able to specify that the template is mixed 
in at the call site.

e.g.,

string mixin template t() { ... }


then

t!(); // is equivalent to mixin(t!()); and no scope issues

The post at

http://forum.dlang.org/thread/wqmngajgejxreyzftrdw forum.dlang.org#post-wqmngajgejxreyzftrdw:40forum.dlang.org

Has an example case where I have to call mixin(tJoin!(...)) to 
generate the code to join the strings. This statement can't be 
wrapped in way to simplify it without defeating the purpose of 
the optimization it gives.

The problem is that when you use variables in a string mixin that 
are outside the template definition and try to string mixin(to 
hide the explicit mixin call), then those variables are outside 
the scope making the call fail.


In the code above, tJoin takes a variadic set of arguments and 
forms a string that concatenates all of them(just as if you typed 
it by hand) but also deals with string arrays by inserting a call 
to a RT function that joins the array.

so the output of tJoin is a code string that can be used to 
concatenate all the arguments passed to it... e.g.,

tJoin!(":", a, b, "c") ==> `a~b~"c"`; if a and b are strings.

mixing in that string, e.g., mixin(tJoin!(":", a, b, "c")), will 
concatenate a with b with c... but only if in the scope of a and 
b. Hence, trying to wrap the mixin statement will change it's 
scope and a and b will either be unknown or wrong.

Having someway to specify that the template should automatically 
be mixed in would help solve these sorts of problems(I've ran 
across it before when trying to generate code using a template 
and avoid the mixin statement).

A few possible options are:

string mixin template t() { ... }

string template t() { ... }

auto mixin template t() { ... }

template t() { ... mixin enum t = ...; }

template t() { ... mixin t = ...; }

etc...
Jul 29 2013
parent reply "nazriel" <spam dzfl.pl> writes:
On Monday, 29 July 2013 at 10:54:37 UTC, JS wrote:
 I have a template t that returns a string that is always to be 
 used as a mixin.

 It is quite annoying to have to use mixin() on the template.

 e.g.,

 mixin(t!());

 It would be nice to be able to specify that the template is 
 mixed in at the call site.

 e.g.,

 string mixin template t() { ... }


 then

 t!(); // is equivalent to mixin(t!()); and no scope issues

 The post at

 http://forum.dlang.org/thread/wqmngajgejxreyzftrdw forum.dlang.org#post-wqmngajgejxreyzftrdw:40forum.dlang.org

 Has an example case where I have to call mixin(tJoin!(...)) to 
 generate the code to join the strings. This statement can't be 
 wrapped in way to simplify it without defeating the purpose of 
 the optimization it gives.

 The problem is that when you use variables in a string mixin 
 that are outside the template definition and try to string 
 mixin(to hide the explicit mixin call), then those variables 
 are outside the scope making the call fail.


 In the code above, tJoin takes a variadic set of arguments and 
 forms a string that concatenates all of them(just as if you 
 typed it by hand) but also deals with string arrays by 
 inserting a call to a RT function that joins the array.

 so the output of tJoin is a code string that can be used to 
 concatenate all the arguments passed to it... e.g.,

 tJoin!(":", a, b, "c") ==> `a~b~"c"`; if a and b are strings.

 mixing in that string, e.g., mixin(tJoin!(":", a, b, "c")), 
 will concatenate a with b with c... but only if in the scope of 
 a and b. Hence, trying to wrap the mixin statement will change 
 it's scope and a and b will either be unknown or wrong.

 Having someway to specify that the template should 
 automatically be mixed in would help solve these sorts of 
 problems(I've ran across it before when trying to generate code 
 using a template and avoid the mixin statement).

 A few possible options are:

 string mixin template t() { ... }

 string template t() { ... }

 auto mixin template t() { ... }

 template t() { ... mixin enum t = ...; }

 template t() { ... mixin t = ...; }

 etc...
You already have mixin templates. Eg: http://dpaste.dzfl.pl/e4b2e17a import core.stdc.stdio; mixin template Test() { class Meh { this() { printf("In Meh"); } } } void main() { mixin Test; Meh m = new Meh(); }
Jul 30 2013
parent reply "JS" <js.mdnq gmail.com> writes:
On Tuesday, 30 July 2013 at 12:19:06 UTC, nazriel wrote:
 On Monday, 29 July 2013 at 10:54:37 UTC, JS wrote:
 I have a template t that returns a string that is always to be 
 used as a mixin.

 It is quite annoying to have to use mixin() on the template.

 e.g.,

 mixin(t!());

 It would be nice to be able to specify that the template is 
 mixed in at the call site.

 e.g.,

 string mixin template t() { ... }


 then

 t!(); // is equivalent to mixin(t!()); and no scope issues

 The post at

 http://forum.dlang.org/thread/wqmngajgejxreyzftrdw forum.dlang.org#post-wqmngajgejxreyzftrdw:40forum.dlang.org

 Has an example case where I have to call mixin(tJoin!(...)) to 
 generate the code to join the strings. This statement can't be 
 wrapped in way to simplify it without defeating the purpose of 
 the optimization it gives.

 The problem is that when you use variables in a string mixin 
 that are outside the template definition and try to string 
 mixin(to hide the explicit mixin call), then those variables 
 are outside the scope making the call fail.


 In the code above, tJoin takes a variadic set of arguments and 
 forms a string that concatenates all of them(just as if you 
 typed it by hand) but also deals with string arrays by 
 inserting a call to a RT function that joins the array.

 so the output of tJoin is a code string that can be used to 
 concatenate all the arguments passed to it... e.g.,

 tJoin!(":", a, b, "c") ==> `a~b~"c"`; if a and b are strings.

 mixing in that string, e.g., mixin(tJoin!(":", a, b, "c")), 
 will concatenate a with b with c... but only if in the scope 
 of a and b. Hence, trying to wrap the mixin statement will 
 change it's scope and a and b will either be unknown or wrong.

 Having someway to specify that the template should 
 automatically be mixed in would help solve these sorts of 
 problems(I've ran across it before when trying to generate 
 code using a template and avoid the mixin statement).

 A few possible options are:

 string mixin template t() { ... }

 string template t() { ... }

 auto mixin template t() { ... }

 template t() { ... mixin enum t = ...; }

 template t() { ... mixin t = ...; }

 etc...
You already have mixin templates. Eg: http://dpaste.dzfl.pl/e4b2e17a import core.stdc.stdio; mixin template Test() { class Meh { this() { printf("In Meh"); } } } void main() { mixin Test; Meh m = new Meh(); }
First how does that remove having to type mixin every time? Second, Mixins are not the same as string mixins.
Jul 30 2013
next sibling parent "nazriel" <spam dzfl.pl> writes:
On Tuesday, 30 July 2013 at 12:25:47 UTC, JS wrote:
 On Tuesday, 30 July 2013 at 12:19:06 UTC, nazriel wrote:
 On Monday, 29 July 2013 at 10:54:37 UTC, JS wrote:
 I have a template t that returns a string that is always to 
 be used as a mixin.

 It is quite annoying to have to use mixin() on the template.

 e.g.,

 mixin(t!());

 It would be nice to be able to specify that the template is 
 mixed in at the call site.

 e.g.,

 string mixin template t() { ... }


 then

 t!(); // is equivalent to mixin(t!()); and no scope issues

 The post at

 http://forum.dlang.org/thread/wqmngajgejxreyzftrdw forum.dlang.org#post-wqmngajgejxreyzftrdw:40forum.dlang.org

 Has an example case where I have to call mixin(tJoin!(...)) 
 to generate the code to join the strings. This statement 
 can't be wrapped in way to simplify it without defeating the 
 purpose of the optimization it gives.

 The problem is that when you use variables in a string mixin 
 that are outside the template definition and try to string 
 mixin(to hide the explicit mixin call), then those variables 
 are outside the scope making the call fail.


 In the code above, tJoin takes a variadic set of arguments 
 and forms a string that concatenates all of them(just as if 
 you typed it by hand) but also deals with string arrays by 
 inserting a call to a RT function that joins the array.

 so the output of tJoin is a code string that can be used to 
 concatenate all the arguments passed to it... e.g.,

 tJoin!(":", a, b, "c") ==> `a~b~"c"`; if a and b are strings.

 mixing in that string, e.g., mixin(tJoin!(":", a, b, "c")), 
 will concatenate a with b with c... but only if in the scope 
 of a and b. Hence, trying to wrap the mixin statement will 
 change it's scope and a and b will either be unknown or wrong.

 Having someway to specify that the template should 
 automatically be mixed in would help solve these sorts of 
 problems(I've ran across it before when trying to generate 
 code using a template and avoid the mixin statement).

 A few possible options are:

 string mixin template t() { ... }

 string template t() { ... }

 auto mixin template t() { ... }

 template t() { ... mixin enum t = ...; }

 template t() { ... mixin t = ...; }

 etc...
You already have mixin templates. Eg: http://dpaste.dzfl.pl/e4b2e17a import core.stdc.stdio; mixin template Test() { class Meh { this() { printf("In Meh"); } } } void main() { mixin Test; Meh m = new Meh(); }
First how does that remove having to type mixin every time? Second, Mixins are not the same as string mixins.
You can a) create wrapper mixin template _(alias T, ARGS...) { mixin(T!(ARGS)); } template Example() { enum Example = "int x = 3;"; } mixin _!Example; b) you can reuse mixin template syntax for your proposal mixin template Proposal() { enum Proposal = "int x = 3;"; } Proposal!(); But I doubt it will happen. As it is disambiguates on call site what Proposal!(); actually does/is. c) enhance template mixin to allow such constructs: mixin template Proposal() { enum Proposal = "int x = 3;"; } mixin Proposal; Still less typing that mixin(Proposal!());
Jul 30 2013
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 30 July 2013 at 12:25:47 UTC, JS wrote:
 First how does that remove having to type mixin every time?
That will *never* happen. Having the keyword *mixin* at call site is important so the caller understand what is actually happening. Without this, you are basically injecting a macro into caller code. Good luck with the re-read.
Jul 30 2013
parent reply "JS" <js.mdnq gmail.com> writes:
On Tuesday, 30 July 2013 at 13:03:47 UTC, monarch_dodra wrote:
 On Tuesday, 30 July 2013 at 12:25:47 UTC, JS wrote:
 First how does that remove having to type mixin every time?
That will *never* happen. Having the keyword *mixin* at call site is important so the caller understand what is actually happening. Without this, you are basically injecting a macro into caller code. Good luck with the re-read.
Um, so? You think my d source is going to be hacked? Someone is going to turn all my templates into string mixins and trick me?
Jul 30 2013
parent reply Kenji Hara <k.hara.pg gmail.com> writes:
Two years ago I proposed the feature with experimental compiler change, but
it was properly rejected.
https://github.com/D-Programming-Language/dmd/pull/459

Kenji Hara


2013/7/30 JS <js.mdnq gmail.com>

 On Tuesday, 30 July 2013 at 13:03:47 UTC, monarch_dodra wrote:

 On Tuesday, 30 July 2013 at 12:25:47 UTC, JS wrote:

 First how does that remove having to type mixin every time?
That will *never* happen. Having the keyword *mixin* at call site is important so the caller understand what is actually happening. Without this, you are basically injecting a macro into caller code. Good luck with the re-read.
Um, so? You think my d source is going to be hacked? Someone is going to turn all my templates into string mixins and trick me?
Jul 30 2013
parent reply "JS" <js.mdnq gmail.com> writes:
On Tuesday, 30 July 2013 at 14:18:20 UTC, Kenji Hara wrote:
 Two years ago I proposed the feature with experimental compiler 
 change, but
 it was properly rejected.
 https://github.com/D-Programming-Language/dmd/pull/459

 Kenji Hara


 2013/7/30 JS <js.mdnq gmail.com>

 On Tuesday, 30 July 2013 at 13:03:47 UTC, monarch_dodra wrote:

 On Tuesday, 30 July 2013 at 12:25:47 UTC, JS wrote:

 First how does that remove having to type mixin every time?
That will *never* happen. Having the keyword *mixin* at call site is important so the caller understand what is actually happening. Without this, you are basically injecting a macro into caller code. Good luck with the re-read.
Um, so? You think my d source is going to be hacked? Someone is going to turn all my templates into string mixins and trick me?
I seriously don't see the issue ;/ By having some special convention for declaring the template then any user of it should have some inclination. Progress isn't made by dumbing down to the lowest common denominator or removing all chances for failure. How bout a simple command line switch to enable the feature?
Jul 30 2013
parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 30 July 2013 at 14:39:31 UTC, JS wrote:
 I seriously don't see the issue ;/ By having some special 
 convention for declaring the template then any user of it 
 should have some inclination. Progress isn't made by dumbing 
 down to the lowest common denominator or removing all chances 
 for failure.

 How bout a simple command line switch to enable the feature?
It is major issue for code readability and clearly separating generated code from manually written one. Reading is always more important than writing when it comes to code.
Jul 30 2013
parent reply "JS" <js.mdnq gmail.com> writes:
On Tuesday, 30 July 2013 at 14:49:44 UTC, Dicebot wrote:
 On Tuesday, 30 July 2013 at 14:39:31 UTC, JS wrote:
 I seriously don't see the issue ;/ By having some special 
 convention for declaring the template then any user of it 
 should have some inclination. Progress isn't made by dumbing 
 down to the lowest common denominator or removing all chances 
 for failure.

 How bout a simple command line switch to enable the feature?
It is major issue for code readability and clearly separating generated code from manually written one. Reading is always more important than writing when it comes to code.
I don't think so. If you write nice code but it is useless then there is no point in anyone reading it. If one allows proper mixin behavior and D ever gets a good ide, then it will be possible to have an intellisense like feature where string mixins are compiled and shown to the user so they can be read properly. If you block every aspect to make using such features easier then few will use them and there usage won't get easier. I think your problem is that you believe if it is not useful to you then it is not useful to anyone else.... or if it confuses you then it will confuse everyone else. It's a very arrogant attitude because everything centers around what you think. You can't expect things to be perfect right from the start... and all of programming is about making life easier for the programmer, not harder. Just because you believe such a feature will make your life more difficult doesn't make it so. The fact is, that string mixins are already hard to read... so just by removing the mixin statement won't change that. The point you are trying to make is flawed. If you are using some library and you call some template and your code blows up and you don't know why... then go read up on that function... there you'll see it is a string mixin. Then, if you get tired of all error obfuscation, go write an ide to make life easier. At some point it will be.... After all, if it were such a big deal then the feature could be removed, and it would not be hard to fix code that used it(just a simple mass search and replace). (this is only true if a special syntax was used to declare such mixins, like "string mixin template_name()". Anyways, it would be nice to actually debate the real merits of such a feature rather than feelings about it.
Jul 30 2013
parent "Dicebot" <public dicebot.lv> writes:
On Tuesday, 30 July 2013 at 19:21:06 UTC, JS wrote:
 I don't think so.
No one will take that from you :)
 If you write nice code but it is useless then there is no point 
 in anyone reading it.
Then don't write useless code. Hint: writing any piece of code longer than N involves reading it even you work alone simply because of limitations of human memory.
 If one allows proper mixin behavior and D ever gets a good ide, 
 then it will be possible to have an intellisense like feature
Please no. Relying on IDE features is a major sign "bad language design".
 If you block every aspect to make using such features easier 
 then few will use them and there usage won't get easier.
Perfect. That is the goal. It is not newbie feature, it is complex feature, it should not be easy to slip into unnoticed.
 I think your problem is that you...
I don't have a problem. You, however, have a problem convincing people who's opinion does matter. Hint: I am not part of that group. I am simply trying to explain in details one possible point of view why this proposal is bad. Can happily retire if you don't need it.
 The fact is, that string mixins are already hard to read... so 
 just by removing the mixin statement won't change that. The 
 point you are trying to make is flawed.
That is irrelevant to actual design of string mixins. There are only very few tools to inject symbols into enclosing scope. Keeping them as explicit is possible is important for code hygiene.
 Anyways, it would be nice to actually debate the real merits of 
 such a feature rather than feelings about it.
Exactly. Merit: saves few symbols. Flaw: someone needs to spend time to implement it. That alone is enough to say "No".
Jul 30 2013