mixin on identifier

Johannes Totz johannes at jo-t.de
Wed Nov 30 03:17:06 PST 2011


On 22/11/2011 21:11, Philippe Sigaud wrote:
> Hi there,
>
> template recursion can get difficult to write sometimes. For the mixin
> part, since what you're doing is looping on States, another solution
> is to use string mixins:
>
> string stateCode(States...)()
> {
>      string code;
>      foreach(state; States)
>          code ~= "mixin " ~ __traits(identifier, state) ~ ";\n";
>      return code;
> }
>
> class StateSet(States...)
> {
>      mixin(stateCode!(States));
> }
>
> void main()
> {
>      auto s = new StateSet!(StateOne, StateTwo)();
>      s.func(1.5);
> }
>
> the 'stateCode' function produces the code you want inside StateSet
> and is then mixed in (by a string mixin, not a template mixin).
> At least to my eyes, the global effect is easier to follow and as a
> bonus you have access to the entire language to manipulate the
> strings: slicing, library functions, etc. Hey, now that CT regex are a
> reality, pretty nifty code manipulation could be done, I guess.
>
>
> Halas, that doesn't change your int/float problem. In the above code,
> s.func(1) doesn't compile.
>
> Strangely, manually inserting the code *does* work:
>
> class StateSet(States...) // I don't care for States
> {
>      int i;
>      void func(int i) { writeln("int: ", i);}
>      float f;
>      void func(float f) { writeln("float: ", f);}
> }
>
> void main()
> {
>      auto s = new StateSet!(StateOne, StateTwo)(); // or whatever
>      s.func(1);
>      s.func(1.0);
> }
>
> So, maybe it's a compiler bug or mixin templates do not work as I
> thought they worked. Because, to me, the resulting code inside
> StateSet should be the same.

Maybe this bug is related: 
http://d.puremagic.com/issues/show_bug.cgi?id=1182
Looks like the functions are not supposed to overload, would need an 
explicit alias.


>
> Workaround: string mixins again:
>
> string StateOne() // Note that it's now a function
> {
>      return q{
>          int i;
>          void func(int i) { writeln("int: ", i);}
>     };
> }
>
> string StateTwo()
> {
>      return q{
>          float f;
>          void func(float f) { writeln("float: ", f);}
>     };
> }
>
> string stateCode(States...)()
> {
>      string code;
>      foreach(state; States) code ~= state ~ ";\n";
>      return code;
> }
>
> class StateSet(States...) // States will here store function names
> {
>      mixin( stateCode!States );
> }
>
> void main()
> {
>      auto s = new StateSet!(StateOne, StateTwo)();
>      s.func(1);
>      s.func(1.0);
> }
>
> On the plus side: it works.
> Disadvantage: you're manipulating strings, so the code 'inside' the
> strings is not checked...
>
> But I get the feeling that tuples should get you what you want. Could
> you expand a bit more on the usage you envision for StateSet?
>
>
> Philippe



More information about the Digitalmars-d-learn mailing list