digitalmars.D.learn - mixin on identifier
- Johannes Totz (23/23) Nov 21 2011 Hi!
- David Nadlinger (4/17) Nov 21 2011 Make T an alias parameter:
- Johannes Totz (29/50) Nov 21 2011 Thanks!
- David Nadlinger (23/75) Nov 21 2011 Turns out to be surprisingly tricky… A possible solution is:
- Johannes Totz (50/141) Nov 22 2011 Thanks a lot, David!
- Philippe Sigaud (82/82) Nov 22 2011 Hi there,
- Johannes Totz (7/88) Nov 30 2011 It's a toy project for me to learn D. I'm trying to recreate something I...
- Johannes Totz (5/87) Nov 30 2011 Maybe this bug is related:
Hi! I'm trying to do: mixin template StateOne() { int value; } class StateSet(T) { mixin T; } int main(string[] argv) { StateSet!StateOne s = new StateSet!StateOne(); return 0; } Compiler complains with: main.d(18): Error: template instance StateSet!(StateOne) StateSet!(StateOne) does not match template declaration StateSet(T) main.d(18): Error: StateSet!(StateOne) is used as a type I think I understand why. And from what I figured I'd need string mixins? But I can't figure out how... Any hints? Johannes
Nov 21 2011
Make T an alias parameter: class StateSet(alias T) { … } David On 11/22/11 12:38 AM, Johannes Totz wrote:mixin template StateOne() { int value; } class StateSet(T) { mixin T; } int main(string[] argv) { StateSet!StateOne s = new StateSet!StateOne(); return 0; }
Nov 21 2011
On 21/11/2011 23:39, David Nadlinger wrote:Make T an alias parameter: class StateSet(alias T) { … } DavidThanks! I was trying to get to something like this: mixin template StateOne() { int value; } mixin template StateTwo() { float data; } class StateSet(alias T ...) { mixin T; } int main(string[] argv) { StateSet!(StateOne, StateTwo) s = new StateSet!(StateOne, StateTwo)(); return 0; } With the docs I got to: template StateSet(alias T, S ...) { class StateSet { mixin T; } } But I have no clue how to expand S into mixin statements.On 11/22/11 12:38 AM, Johannes Totz wrote:mixin template StateOne() { int value; } class StateSet(T) { mixin T; } int main(string[] argv) { StateSet!StateOne s = new StateSet!StateOne(); return 0; }
Nov 21 2011
Turns out to be surprisingly tricky… A possible solution is: mixin template StateOne() { int value; } mixin template StateTwo() { float data; } mixin template MixinAll(T...) { static if (T.length > 0) { alias T[0] A; mixin A; mixin MixinAll!(T[1 .. $]); } } class StateSet(T...){ mixin MixinAll!T; } void main() { auto s = new StateSet!(StateOne, StateTwo)(); } Hope this helps, David On 11/22/11 1:02 AM, Johannes Totz wrote:On 21/11/2011 23:39, David Nadlinger wrote:Make T an alias parameter: class StateSet(alias T) { … } DavidThanks! I was trying to get to something like this: mixin template StateOne() { int value; } mixin template StateTwo() { float data; } class StateSet(alias T ...) { mixin T; } int main(string[] argv) { StateSet!(StateOne, StateTwo) s = new StateSet!(StateOne, StateTwo)(); return 0; } With the docs I got to: template StateSet(alias T, S ...) { class StateSet { mixin T; } } But I have no clue how to expand S into mixin statements.On 11/22/11 12:38 AM, Johannes Totz wrote:mixin template StateOne() { int value; } class StateSet(T) { mixin T; } int main(string[] argv) { StateSet!StateOne s = new StateSet!StateOne(); return 0; }
Nov 21 2011
On 22/11/2011 04:57, David Nadlinger wrote:Turns out to be surprisingly tricky… A possible solution is: mixin template StateOne() { int value; } mixin template StateTwo() { float data; } mixin template MixinAll(T...) { static if (T.length > 0) { alias T[0] A; mixin A; mixin MixinAll!(T[1 .. $]); } } class StateSet(T...){ mixin MixinAll!T; } void main() { auto s = new StateSet!(StateOne, StateTwo)(); } Hope this helps, DavidThanks a lot, David! A new variant of this (notice the func()s): mixin template StateOne() { int value; void func(int d) { value = d; } } mixin template StateTwo() { float data; void func(float d) { data = d; } } mixin template MixinAll(T...) { static if (T.length > 0) { alias T[0] A; mixin A; mixin MixinAll!(T[1 .. $]); } } class StateSet(T...) { mixin MixinAll!T; } int main(string[] argv) { auto s = new StateSet!(StateOne, StateTwo)(); s.value = 1; s.data = 3.1f; s.func(2); // Error s.func(4.5f); // Ok return 0; } Error: main.StateSet!(StateOne,StateTwo).StateSet.MixinAll!(StateOne,StateTwo).MixinAll! StateTwo).A!().func at main.d(20) conflicts with main.StateSet!(StateOne,StateTwo).StateSet.MixinAll!(StateOne StateTwo).A!().func at main.d(10) I suppose I get the error at the first func() call because int is implicitly convertible to float. Is it really? Also, I tried to make the mixed-in members private/etc but this does not seem to have any effect...On 11/22/11 1:02 AM, Johannes Totz wrote:On 21/11/2011 23:39, David Nadlinger wrote:Make T an alias parameter: class StateSet(alias T) { … } DavidThanks! I was trying to get to something like this: mixin template StateOne() { int value; } mixin template StateTwo() { float data; } class StateSet(alias T ...) { mixin T; } int main(string[] argv) { StateSet!(StateOne, StateTwo) s = new StateSet!(StateOne, StateTwo)(); return 0; } With the docs I got to: template StateSet(alias T, S ...) { class StateSet { mixin T; } } But I have no clue how to expand S into mixin statements.On 11/22/11 12:38 AM, Johannes Totz wrote:mixin template StateOne() { int value; } class StateSet(T) { mixin T; } int main(string[] argv) { StateSet!StateOne s = new StateSet!StateOne(); return 0; }
Nov 22 2011
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. 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
Nov 22 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. 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); }Thanks!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?It's a toy project for me to learn D. I'm trying to recreate something I wrote in C++ once. It used extremely messy MPL to have a class inherit individual states from template parameters. But the problem was that func() would not overload from inherited classes. So I tought D's mixins might be suitable.
Nov 30 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
Nov 30 2011