digitalmars.D.learn - Templates and stringof...
- Era Scarecrow (15/15) Aug 03 2012 While working on bitfields code I've found a unique scenario
- David Nadlinger (5/7) Aug 03 2012 You don't. Using .stringof in conjunction with string mixins is
- Era Scarecrow (7/14) Aug 03 2012 Because a string doesn't hold it's type information for size
- David Nadlinger (4/10) Aug 03 2012 Just emit the check into the code you generate.
- Andrej Mitrovic (30/32) Aug 03 2012 Courtesy of Philippe Sigaud, slightly edited to my style:
- Andrej Mitrovic (3/7) Aug 03 2012 Ahh crap, it doesn't return the *instance* name. Sorry!! Maybe there
- Era Scarecrow (8/16) Aug 03 2012 Mmmm worse comes to worse i can do a mixin, which generates the
- David Nadlinger (14/19) Aug 03 2012 This can't work in general. What should such a function return?
- Era Scarecrow (10/28) Aug 03 2012 I would think, the exact 'text' of the way the variable was
- Philippe Sigaud (21/26) Aug 04 2012 method of fullpathStringof or something similar? Then again if this is o...
- Era Scarecrow (8/19) Aug 04 2012 If traits will work, then that's what we go with. I've already
- David Nadlinger (13/16) Aug 04 2012 An example of what I mean: Try this with your CurryTemplate from
- Philippe Sigaud (7/16) Aug 04 2012 Oh, I completely forgot this. Nice code, if I may say so myself :)
- David Nadlinger (5/7) Aug 04 2012 Huh? It's broken, precisely because of the use of
- Philippe Sigaud (5/10) Aug 04 2012 Yes, I know :) I does desmontrate your point, you convinced me. But
- Jonathan M Davis (4/7) Aug 04 2012 That and std.traits. Between those two and the power of is expressions, ...
- David Nadlinger (5/14) Aug 04 2012 There is nothing wrong about __traits, just about .stringof resp.
- Andrej Mitrovic (4/8) Aug 03 2012 In fact, this should really be put into Phobos so everyone can benefit
- David Nadlinger (4/11) Aug 03 2012 No, it shouldn't be. There are almost no legit use cases for it,
- Era Scarecrow (29/36) Aug 03 2012 Then doesn't it seem like we're missing a potentially important
- Philippe Sigaud (14/18) Aug 04 2012 the puzzle for mixins and templates? very likely my modified template wi...
While working on bitfields code I've found a unique scenario that poses some annoyances when generating the code. template XYZ(alias x) { enum XYZ = x.stringof ~ "=100;"; } struct I { int i;} I i_num; int n; mixin(XYZ!(i_num.i)); //cannot find variable i mixin(XYZ!(n)); the mixins become: i=100; n=100; Now, how do I get the template's stringof to print out 'i_num.i' and not 'i'?
Aug 03 2012
On Friday, 3 August 2012 at 21:02:22 UTC, Era Scarecrow wrote:Now, how do I get the template's stringof to print out 'i_num.i' and not 'i'?You don't. Using .stringof in conjunction with string mixins is The Wrong Thing (tm) in virtually all cases. What do you want to achieve? Why can't you pass a string instead? David
Aug 03 2012
On Friday, 3 August 2012 at 21:19:08 UTC, David Nadlinger wrote:On Friday, 3 August 2012 at 21:02:22 UTC, Era Scarecrow wrote:Because a string doesn't hold it's type information for size checking. int = 4 bytes or 32 bits string = ???? It also checks for unsuitable types like structs and floats; can't do that with strings.Now, how do I get the template's stringof to print out 'i_num.i' and not 'i'?You don't. Using .stringof in conjunction with string mixins is The Wrong Thing (tm) in virtually all cases. What do you want to achieve? Why can't you pass a string instead?
Aug 03 2012
On Friday, 3 August 2012 at 21:33:35 UTC, Era Scarecrow wrote:Because a string doesn't hold it's type information for size checking. int = 4 bytes or 32 bits string = ????Just emit the check into the code you generate.It also checks for unsuitable types like structs and floats; can't do that with strings.Just emit the check into the code you generate. David
Aug 03 2012
On 8/3/12, Era Scarecrow <rtcvb32 yahoo.com> wrote:Now, how do I get the template's stringof to print out 'i_num.i' and not 'i'?Courtesy of Philippe Sigaud, slightly edited to my style: /** Return the fully qualified name of a symbol. Implemented by Philippe Sigaud in the D Templates book. See https://github.com/PhilippeSigaud/D-templates-tutorial */ template ScopedName(alias a) { // does it have a parent? static if (__traits(compiles, __traits(parent, a))) { // If yes, get the name and recurse enum ScopedName =3D ScopedName!(__traits (parent, a)) ~ "." ~ NameO= f!(a); } else { // if not, it=92s a module name. Stop there. enum ScopedName =3D NameOf!a; } } template NameOf(alias a) { enum string NameOf =3D __traits(identifier, a); } template XYZ(alias x) { enum XYZ =3D ScopedName!x ~ "=3D100;"; }
Aug 03 2012
On 8/4/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:On 8/3/12, Era Scarecrow <rtcvb32 yahoo.com> wrote:Ahh crap, it doesn't return the *instance* name. Sorry!! Maybe there can be a fix though, I'll give it a try..Now, how do I get the template's stringof to print out 'i_num.i' and not 'i'?snip
Aug 03 2012
On Friday, 3 August 2012 at 22:18:25 UTC, Andrej Mitrovic wrote:On 8/4/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Mmmm worse comes to worse i can do a mixin, which generates the text into it's non-text verision and passes both to my template which then does it's appropriate checks. Seems like an ugly hack though (to get this done). Why not have another method of fullpathStringof or something similar? Then again if this is one of the few cases that could benefit from it, then maybe we should make it ugly so no one else will use it.On 8/3/12, Era Scarecrow <rtcvb32 yahoo.com> wrote:Ahh crap, it doesn't return the *instance* name. Sorry!! Maybe there can be a fix though, I'll give it a try..Now, how do I get the template's stringof to print out 'i_num.i' and not 'i'?snip
Aug 03 2012
On Friday, 3 August 2012 at 22:23:23 UTC, Era Scarecrow wrote:Seems like an ugly hack though (to get this done). Why not have another method of fullpathStringof or something similar? Then again if this is one of the few cases that could benefit from it, then maybe we should make it ugly so no one else will use it.This can't work in general. What should such a function return? The fully qualified name, i.e. including packages and modules? What is if the referred to entity is a nested function/local variable? What is if it is defined in a module which is not imported in the place where the string is mixed in? Regarding Philippe Sigaud's stuff: He has done a lot of great work, but exactly this use of strings is why some of his template constructions are not usable in the real world. Again, using .stringof in conjunction with string mixins is almost never a good idea. Please trust me on this, I've done quite a bit of metaprogramming-heavy projects, and there are always ways around this, which are often more elegant as well. David
Aug 03 2012
On Friday, 3 August 2012 at 22:47:52 UTC, David Nadlinger wrote:On Friday, 3 August 2012 at 22:23:23 UTC, Era Scarecrow wrote:I would think, the exact 'text' of the way the variable was called, in my example it would be "inum.i", and since it would be at the local level (where the mixin was called) it should have access to everything that it did at that time.Seems like an ugly hack though (to get this done). Why not have another method of fullpathStringof or something similar? Then again if this is one of the few cases that could benefit from it, then maybe we should make it ugly so no one else will use it.This can't work in general. What should such a function return? The fully qualified name, I.e. including packages and modules? What is if the referred to entity is a nested function/local variable? What is if it is defined in a module which is not imported in the place where the string is mixed in?Regarding Philippe Sigaud's stuff: He has done a lot of great work, but exactly this use of strings is why some of his template constructions are not usable in the real world. Again, using .stringof in conjunction with string mixins is almost never a good idea. Please trust me on this, I've done quite a bit of metaprogramming-heavy projects, and there are always ways around this, which are often more elegant as well.I have limited experience making and using templates, so I'll have to believe you; But it still seems like there should be a much better way than an uber-ugly work around. One of the reasons I want to use an alias vs a string, is so I can use the constraints the way they are suppose to be.
Aug 03 2012
Le 4 ao=C3=BBt 2012 00:50, "David Nadlinger" <see klickverbot.at> a =C3=A9c= rit :On Friday, 3 August 2012 at 22:23:23 UTC, Era Scarecrow wrote:method of fullpathStringof or something similar? Then again if this is one of the few cases that could benefit from it, then maybe we should make it ugly so no one else will use it.Seems like an ugly hack though (to get this done). Why not have anotherThis can't work in general. What should such a function return? The fullyqualified name, i.e. including packages and modules? What is if the referred to entity is a nested function/local variable? What is if it is defined in a module which is not imported in the place where the string is mixed in?Regarding Philippe Sigaud's stuff: He has done a lot of great work, butexactly this use of strings is why some of his template constructions are not usable in the real world. Again, using .stringof in conjunction with string mixins is almost never a good idea. FWIW, I agree with David that using .stringof is a last resort and can lead to nasty bugs. .stringof has a sometime incoherent behavior (I remember it showing the entire code inside a delegate literal) But then, the code shown upstream do *not* use .stringof. It uses __traits(parent, ) and __traits(qualifier, ), which are much more 'modern' and well-behaved. For std.reflection that Andrei proposed 2 weeks ago, I feel the internal code will contain many __traits() calls. Nothing to be done about it. __traits is *the* way compile-time introspection is done in D.
Aug 04 2012
On Saturday, 4 August 2012 at 07:57:46 UTC, Philippe Sigaud wrote:FWIW, I agree with David that using .stringof is a last resort and can lead to nasty bugs. .stringof has a sometime incoherent behavior (I remember it showing the entire code inside a delegate literal)But then, the code shown upstream do *not* use .stringof. It uses __traits(parent, ) and __traits(qualifier, ), which are much more 'modern' and well-behaved.For std.reflection that Andrei proposed 2 weeks ago, I feel the internal code will contain many __traits() calls. Nothing to be done about it. __traits is *the* way compile-time introspection is done in D.If traits will work, then that's what we go with. I've already got a workaround for what I need, a template creating a mixin, that you use a mixin on to make the bitfields; not pretty, but it will do the job; at least until a better option shows itself, preferably in a template in std.traits I can use and not go lower-level than I have to. Sorry if I've taken up unnecessary time.
Aug 04 2012
On Saturday, 4 August 2012 at 07:57:46 UTC, Philippe Sigaud wrote:It uses __traits(parent, ) and __traits(qualifier, ), which are much more 'modern' and well-behaved.An example of what I mean: Try this with your CurryTemplate from dranges: --- import dranges.templates; template Foo(A, B) { pragma(msg, A.stringof, " ", B.stringof); } alias CurryTemplate!Foo FooCurried; alias FooCurried!int FooInt; alias FooInt!string Test; --- David
Aug 04 2012
On Sat, Aug 4, 2012 at 10:25 AM, David Nadlinger <see klickverbot.at> wrote:An example of what I mean: Try this with your CurryTemplate from dranges: --- import dranges.templates; template Foo(A, B) { pragma(msg, A.stringof, " ", B.stringof); } alias CurryTemplate!Foo FooCurried; alias FooCurried!int FooInt; alias FooInt!string Test;Oh, I completely forgot this. Nice code, if I may say so myself :) But yes, having identifiers going back and forth between modules is difficult. I didn't realize this in 2009, while most of dranges was written. Now, since I regularly need to have a template work on local identifiers, I tend to use mixins much more than in dtemplates.
Aug 04 2012
On Saturday, 4 August 2012 at 11:29:36 UTC, Philippe Sigaud wrote:Oh, I completely forgot this. Nice code, if I may say so myself :)Huh? It's broken, precisely because of the use of __traits(identifier, …) in combination with string mixins. The example doesn't compile. David
Aug 04 2012
On Sat, Aug 4, 2012 at 1:35 PM, David Nadlinger <see klickverbot.at> wrote:On Saturday, 4 August 2012 at 11:29:36 UTC, Philippe Sigaud wrote:=E2=80=A6) inOh, I completely forgot this. Nice code, if I may say so myself :)Huh? It's broken, precisely because of the use of __traits(identifier, =combination with string mixins. The example doesn't compile.Yes, I know :) I does desmontrate your point, you convinced me. But the code was from a long time ago and I have sweet spot for nested static ifs :)
Aug 04 2012
On Saturday, August 04, 2012 09:57:36 Philippe Sigaud wrote:For std.reflection that Andrei proposed 2 weeks ago, I feel the internal code will contain many __traits() calls. Nothing to be done about it. __traits is *the* way compile-time introspection is done in D.That and std.traits. Between those two and the power of is expressions, that's where the ability to do compile-time introspection comes from. - Jonathan M Davis
Aug 04 2012
On Saturday, 4 August 2012 at 08:06:31 UTC, Jonathan M Davis wrote:On Saturday, August 04, 2012 09:57:36 Philippe Sigaud wrote:There is nothing wrong about __traits, just about .stringof resp. __traits(identifier) in conjunction with string mixins. DavidFor std.reflection that Andrei proposed 2 weeks ago, I feel the internal code will contain many __traits() calls. Nothing to be done about it. __traits is *the* way compile-time introspection is done in D.That and std.traits. Between those two and the power of is expressions, that's where the ability to do compile-time introspection comes from.
Aug 04 2012
On 8/4/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:On 8/3/12, Era Scarecrow <rtcvb32 yahoo.com> wrote:In fact, this should really be put into Phobos so everyone can benefit rather than implementing this internally as a private template of bitmanip.Now, how do I get the template's stringof to print out 'i_num.i' and not 'i'?Courtesy of Philippe Sigaud, slightly edited to my style:
Aug 03 2012
On Friday, 3 August 2012 at 22:44:28 UTC, Andrej Mitrovic wrote:On 8/4/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:No, it shouldn't be. There are almost no legit use cases for it, and having it in the library encourages abuse of string mixins/stringof in cases like this one.Courtesy of Philippe Sigaud, slightly edited to my style:In fact, this should really be put into Phobos so everyone can benefit rather than implementing this internally as a private template of bitmanip.
Aug 03 2012
On Friday, 3 August 2012 at 22:50:54 UTC, David Nadlinger wrote:On Friday, 3 August 2012 at 22:44:28 UTC, Andrej Mitrovic wrote:Then doesn't it seem like we're missing a potentially important piece of the puzzle for mixins and templates? very likely my modified template will include you including the same variable twice, but if someone gets lazy then it may not work. mixin(bitfieldsOn!("SomeVariable", SomeVariable, /*stuff*/)); // or mixin(bitfieldsOn!("SomeVariable", variable type, /*stuff*/)); But if it comes to it, what if they use auto or point to something else just to make it shut up? Constraints will let it pass but the code will pop up with errors that may not be reasonably readable. long l; float fl; mixin(bitfieldsOn!("fl", l, /*stuff*/)); //by name, typo or lazy //or mixin(bitfieldsOn!("fl", auto, /*stuff*/)); //explicit type, lazy or lying Now the checks pass but the compile code works wrong. True I can add asserts as part of the output code, but as mentioned hopefully the constraints could do that work, plus adding extra checks as part of a mixin seems a little... excessive. Let's assume we use 'localStringof' or 'callingStringof' and that it returns the string of how the variable is called/referenced; Give me some examples how it would be abused or used wrongly? Aliased variables are pretty much perfect forwarded in templates (Unless my understanding is off) so they would carry that information forward.In fact, this should really be put into Phobos so everyone can benefit rather than implementing this internally as a private template of bitmanip.No, it shouldn't be. There are almost no legit use cases for it, and having it in the library encourages abuse of string mixins/stringof in cases like this one.
Aug 03 2012
"Era Scarecrow" <rtcvb32 yahoo.com>Then doesn't it seem like we're missing a potentially important piece ofthe puzzle for mixins and templates? very likely my modified template will include you including the same variable twice, but if someone gets lazy then it may not work.mixin(bitfieldsOn!("SomeVariable", SomeVariable, /*stuff*/)); // or mixin(bitfieldsOn!("SomeVariable", variable type, /*stuff*/));Hmm. You can ask for just the name as a string (so, qualified or not, as the user wish) and include a test for the type of the passed name. inside bitfieldsOn: mixin(" static if is(typeof("~name~")) alias typeof(" ~ name ~ ") NameType; else static assert(false, `bad name given to bitfieldsOn:"~name~".`); ") Untested, I'm on a pad right now.
Aug 04 2012