digitalmars.D.learn - mixin troubles
- Derek Parnell (47/47) Oct 02 2006 Ok, I'm the first to admit that I don't understand the syntax of mixins....
- Jarrett Billingsley (30/68) Oct 03 2006 Mixins bug me too. Here's the "correct" version of your code:
- Derek Parnell (23/85) Oct 03 2006 Thanks for patience.
- Chris Nicholson-Sauls (7/56) Oct 03 2006 I may be wrong, but I think you could do this:
- Derek Parnell (12/67) Oct 04 2006 No such luck ...
- Jarrett Billingsley (19/24) Oct 04 2006 Almost, you "just" have to split it out into an alias:
- Josh Stern (23/87) Oct 05 2006 I think the double use of "Foo" for the template namespace and the
- Derek Parnell (24/28) Oct 05 2006 I think you have missed my point.
- Josh Stern (34/65) Oct 05 2006 Yes, I missed the point that the special difficulty being addressed was
- Derek Parnell (28/29) Oct 05 2006 Thank you. This was the key information that I didn't pick up from the
- Josh Stern (8/40) Oct 05 2006 You can't use exactly the same name - i.e. mixin .FFoo!(a) a;
- Kristian (6/31) Oct 06 2006 Yep, that would be very useful.
Ok, I'm the first to admit that I don't understand the syntax of mixins. It just seems *SO* unintuitive that it never sticks in my mind, and when I look up the documentation I find that it is misleading and/or wrong. Anyhow, what am I doing wrong here ... template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin Foo!(a) y; mixin Foo!(b) z; assert(y() == 3); assert(z() == 3.14); } I was expecting that code to be equivalent to ... void main() { int a = 3; double b = 3.14; typeof(a) y() { return a; } typeof(b) z() { return b; } assert(y() == 3); assert(z() == 3.14); } BTW, the docs say that the instantiation syntax for mixins is mixin Foo!() a y; that is that the template arguments are placed outside and following the parenthesis, but that has just got to be wrong. I quote ... " TemplateMixin: mixin TemplateIdentifier ; mixin TemplateIdentifier MixinIdentifier ; mixin TemplateIdentifier !() TemplateArgumentList ; mixin TemplateIdentifier !() TemplateArgumentList MixinIdentifier ; MixinIdentifier: Identifier " -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 3/10/2006 2:42:56 PM
Oct 02 2006
"Derek Parnell" <derek nomail.afraid.org> wrote in message news:327lkdzeqky1$.11w3vhc3ana9f.dlg 40tude.net...Anyhow, what am I doing wrong here ... template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin Foo!(a) y; mixin Foo!(b) z; assert(y() == 3); assert(z() == 3.14); }Mixins bug me too. Here's the "correct" version of your code: template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin .Foo!(a) y; mixin .Foo!(b) z; assert(y.Foo() == 3); assert(z.Foo() == 3.14); } Notice the global scope operators on the mixin instantiations, and the explicit access of y.Foo/z.Foo. The reason this happens is that the first mixin Foo!(a) y; mixes in the symbol Foo from inside the template. Then the second mixin attempts to use the local Foo, which is now a mixed-in function, as a template, which fails. So you have to use the global scope operator to access the actual template declaration. (Actually the first one is optional.) Then, you can't call y(), because although the function Foo is the same name as the mixin Foo, y is of type mixin Foo!(a), and the compiler doesn't interpret y() as a call to Foo.I was expecting that code to be equivalent to ... void main() { int a = 3; double b = 3.14; typeof(a) y() { return a; } typeof(b) z() { return b; } assert(y() == 3); assert(z() == 3.14); }It would be great to be able to generate code like that.BTW, the docs say that the instantiation syntax for mixins is mixin Foo!() a y; that is that the template arguments are placed outside and following the parenthesis, but that has just got to be wrong. I quote ... " TemplateMixin: mixin TemplateIdentifier ; mixin TemplateIdentifier MixinIdentifier ; mixin TemplateIdentifier !() TemplateArgumentList ; mixin TemplateIdentifier !() TemplateArgumentList MixinIdentifier ; MixinIdentifier: Identifier "I've noticed this in a lot of places in the docs; it showed up when Walter converted them all over to DDoc format. A lot of the instances have been fixed. I think he might just have his DDoc macros wrong.
Oct 03 2006
On Wed, 4 Oct 2006 00:03:17 -0400, Jarrett Billingsley wrote:"Derek Parnell" <derek nomail.afraid.org> wrote in message news:327lkdzeqky1$.11w3vhc3ana9f.dlg 40tude.net...Thanks for patience.Anyhow, what am I doing wrong here ... template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin Foo!(a) y; mixin Foo!(b) z; assert(y() == 3); assert(z() == 3.14); }Mixins bug me too. Here's the "correct" version of your code:template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin .Foo!(a) y; mixin .Foo!(b) z; assert(y.Foo() == 3); assert(z.Foo() == 3.14); } Notice the global scope operators on the mixin instantiations, and the explicit access of y.Foo/z.Foo. The reason this happens is that the first mixin Foo!(a) y; mixes in the symbol Foo from inside the template. Then the second mixin attempts to use the local Foo, which is now a mixed-in function, as a template, which fails. So you have to use the global scope operator to access the actual template declaration. (Actually the first one is optional.) Then, you can't call y(), because although the function Foo is the same name as the mixin Foo, y is of type mixin Foo!(a), and the compiler doesn't interpret y() as a call to Foo.Ok, I can see the reasoning behind that now and it does make sense in a strict, pedantic, form ... but OMG that is *such* a horrible mess! I thought programming languages were supposed to make programming easier.And IMHO a lot more intuitive. In fact my first attempt was this ... template Foo(alias a, alias b) { typeof(b) a() { return b; } } . . . mixin Foo!(y,3); assert(y() == 3); because I thought that the documentation meant 'alias' performs lexical symbol substitution rather than whatever it does mean, which I still can't quite interpret. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 4/10/2006 2:26:53 PMI was expecting that code to be equivalent to ... void main() { int a = 3; double b = 3.14; typeof(a) y() { return a; } typeof(b) z() { return b; } assert(y() == 3); assert(z() == 3.14); }It would be great to be able to generate code like that.
Oct 03 2006
Derek Parnell wrote:On Wed, 4 Oct 2006 00:03:17 -0400, Jarrett Billingsley wrote:I may be wrong, but I think you could do this: -- Chris Nicholson-Sauls"Derek Parnell" <derek nomail.afraid.org> wrote in message news:327lkdzeqky1$.11w3vhc3ana9f.dlg 40tude.net...Thanks for patience.Anyhow, what am I doing wrong here ... template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin Foo!(a) y; mixin Foo!(b) z; assert(y() == 3); assert(z() == 3.14); }Mixins bug me too. Here's the "correct" version of your code:template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin .Foo!(a) y; mixin .Foo!(b) z; assert(y.Foo() == 3); assert(z.Foo() == 3.14); } Notice the global scope operators on the mixin instantiations, and the explicit access of y.Foo/z.Foo.
Oct 03 2006
On Wed, 04 Oct 2006 01:55:45 -0500, Chris Nicholson-Sauls wrote:Derek Parnell wrote:No such luck ... test.d(10): template instance cannot use local 'a' as template parameter test.d(3): function test.Foo!(a).Foo cannot access frame of function main test.d(10): template instance test.Foo!(a) error instantiating test.d(10): mixin Foo!() is not defined -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 4/10/2006 5:01:36 PMOn Wed, 4 Oct 2006 00:03:17 -0400, Jarrett Billingsley wrote:I may be wrong, but I think you could do this:"Derek Parnell" <derek nomail.afraid.org> wrote in message news:327lkdzeqky1$.11w3vhc3ana9f.dlg 40tude.net...Thanks for patience.Anyhow, what am I doing wrong here ... template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin Foo!(a) y; mixin Foo!(b) z; assert(y() == 3); assert(z() == 3.14); }Mixins bug me too. Here's the "correct" version of your code:template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin .Foo!(a) y; mixin .Foo!(b) z; assert(y.Foo() == 3); assert(z.Foo() == 3.14); } Notice the global scope operators on the mixin instantiations, and the explicit access of y.Foo/z.Foo.
Oct 04 2006
"Derek Parnell" <derek nomail.afraid.org> wrote in message news:kawtg2nmq5d6$.1dp41k208dts4.dlg 40tude.net...No such luck ... test.d(10): template instance cannot use local 'a' as template parameter test.d(3): function test.Foo!(a).Foo cannot access frame of function main test.d(10): template instance test.Foo!(a) error instantiating test.d(10): mixin Foo!() is not definedAlmost, you "just" have to split it out into an alias: template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 2; float b = 3.25; mixin .Foo!(a) tempX; mixin .Foo!(b) tempY; alias tempX.Foo x; alias tempY.Foo y; assert(x() == 2); assert(y() == 3.25); } That works. And is the ugliest thing ever.
Oct 04 2006
I think the double use of "Foo" for the template namespace and the function itself made the example confusing. The following works and makes the role of the template and the function and/or class names clearer (no alias really needed): import std.stdio; template FFoo(alias b) { typeof(b) foo() { return b; } // foo function class FooClass { typeof(b) opCall() { return b; } // operator() in FooClass } } void main() { int a=5; mixin .FFoo!(a); // instantiates foo() and FooClass using local a as parameter int y = foo(); writefln(y); FooClass obj = new FooClass; y = obj(); writefln(y); } On Wed, 04 Oct 2006 17:02:15 +1000, Derek Parnell wrote:On Wed, 04 Oct 2006 01:55:45 -0500, Chris Nicholson-Sauls wrote:Derek Parnell wrote:No such luck ... test.d(10): template instance cannot use local 'a' as template parameter test.d(3): function test.Foo!(a).Foo cannot access frame of function main test.d(10): template instance test.Foo!(a) error instantiating test.d(10): mixin Foo!() is not definedOn Wed, 4 Oct 2006 00:03:17 -0400, Jarrett Billingsley wrote:I may be wrong, but I think you could do this:"Derek Parnell" <derek nomail.afraid.org> wrote in message news:327lkdzeqky1$.11w3vhc3ana9f.dlg 40tude.net...Thanks for patience.Anyhow, what am I doing wrong here ... template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin Foo!(a) y; mixin Foo!(b) z; assert(y() == 3); assert(z() == 3.14); }Mixins bug me too. Here's the "correct" version of your code:template Foo(alias b) { typeof(b) Foo() { return b; } } void main() { int a = 3; double b = 3.14; mixin .Foo!(a) y; mixin .Foo!(b) z; assert(y.Foo() == 3); assert(z.Foo() == 3.14); } Notice the global scope operators on the mixin instantiations, and the explicit access of y.Foo/z.Foo.
Oct 05 2006
On Thu, 05 Oct 2006 14:28:01 -0500, Josh Stern wrote:I think the double use of "Foo" for the template namespace and the function itself made the example confusing. The following works and makes the role of the template and the function and/or class names clearer (no alias really needed):I think you have missed my point. I want to mixin the template multiple times, each time giving the resulting statement a different identifier so it can be used in a simple manner. For example, using your 'different' name idea ... import std.stdio; template FFoo(alias b) { typeof(b) foo() { return b; } // foo function } void main() { int a=5; double b = 3.14; // FIRST TIME mixin .FFoo!(a) x; // bring in the statement calling it 'x' writefln( x() ); // SECONND TIME mixin .FFoo!(b) y; // bring it in again but call it 'y' this time. writefln( y() ); } This still fails and yet looks intuitive (to me at least). -- Derek Parnell Melbourne, Australia "Down with mediocrity!"
Oct 05 2006
On Fri, 06 Oct 2006 09:04:05 +1000, Derek Parnell wrote:On Thu, 05 Oct 2006 14:28:01 -0500, Josh Stern wrote:Yes, I missed the point that the special difficulty being addressed was trying to avoid a name clash caused by multiple definitions. But even so, mixins and template seem to interact in the way I would expect and I don't see that alias's are really required. You have two good choices here - either use the 'x' and 'y' extra level of namespace idea... import std.stdio; template FFoo(alias b) { typeof(b) foo() { return b; } // foo function } void main() { int a=5; double b = 3.14; // FIRST TIME mixin .FFoo!(a) x; // bring in the statement in the 'x' sub-namespace writefln(x.foo()); // SECOND TIME mixin .FFoo!(b) y; // bring it in in the 'y' sub-namespace. writefln(y.foo()); } ...or just use an extra level of braces around each distinct instantiation... { //First time mixin .FFoo!(a); } { // Second time mixin .FFoo!(b); writefln( foo()); }I think the double use of "Foo" for the template namespace and the function itself made the example confusing. The following works and makes the role of the template and the function and/or class names clearer (no alias really needed):I think you have missed my point. I want to mixin the template multiple times, each time giving the resulting statement a different identifier so it can be used in a simple manner.For example, using your 'different' name idea ... import std.stdio; template FFoo(alias b) { typeof(b) foo() { return b; } // foo function } void main() { int a=5; double b = 3.14; // FIRST TIME mixin .FFoo!(a) x; // bring in the statement calling it 'x' writefln( x() ); // SECONND TIME mixin .FFoo!(b) y; // bring it in again but call it 'y' this time. writefln( y() ); } } } This still fails and yet looks intuitive (to me at least).I think of mixin as a smart replacement for macros so I wouldn't expect the above to work.
Oct 05 2006
On Thu, 05 Oct 2006 18:55:44 -0500, Josh Stern wrote:mixin .FFoo!(a) x; // bring in the statement in the 'x' sub-namespaceThank you. This was the key information that I didn't pick up from the docs. It is documented but I didn't get it until now. The important passage from the docs is "A mixin has its own scope". I kept on reading that as "the mixin's template has its own scope" but now I understand it is the mixin statement itself that creates a new scope/namespace, and that the "MixinIdentifier" is the optional name one can give to that scope. Then one can use the MixinIdentifier as a namespace qualifier to disambiguate identifiers brought in by the mixin statements. Mind you, this would have been made easier if the 'alias' argument could also have been used to 'set' the identifier declared in the template. In other words it would have been 'smart' for mixin to allow ... template foo(alias a, alias b) { typeof(b) a(b) { . . . } } mixin foo!(Bar, 3); mixin foo!(Qwe, 3.14); to generate code as ... typeof(3) Bar(3) { . . . } typeof(3.14) Qwe(3.14) { . . . } then there would have been no disambiguation required. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 6/10/2006 10:33:50 AM
Oct 05 2006
On Fri, 06 Oct 2006 10:43:59 +1000, Derek Parnell wrote:On Thu, 05 Oct 2006 18:55:44 -0500, Josh Stern wrote:You can't use exactly the same name - i.e. mixin .FFoo!(a) a; But you could adopt some convention of related names - i.e. mixin .FFoo!(a) for_a; mixin .FFoo!(b) for_b; for_a.foo(); for_b.foo(); etc.mixin .FFoo!(a) x; // bring in the statement in the 'x' sub-namespaceThank you. This was the key information that I didn't pick up from the docs. It is documented but I didn't get it until now. The important passage from the docs is "A mixin has its own scope". I kept on reading that as "the mixin's template has its own scope" but now I understand it is the mixin statement itself that creates a new scope/namespace, and that the "MixinIdentifier" is the optional name one can give to that scope. Then one can use the MixinIdentifier as a namespace qualifier to disambiguate identifiers brought in by the mixin statements. Mind you, this would have been made easier if the 'alias' argument could also have been used to 'set' the identifier declared in the template.In other words it would have been 'smart' for mixin to allow ... template foo(alias a, alias b) { typeof(b) a(b) { . . . } } mixin foo!(Bar, 3); mixin foo!(Qwe, 3.14); to generate code as ... typeof(3) Bar(3) { . . . } typeof(3.14) Qwe(3.14) { . . . } then there would have been no disambiguation required.
Oct 05 2006
On Fri, 06 Oct 2006 03:43:59 +0300, Derek Parnell <derek nomail.afraid.org> wrote:On Thu, 05 Oct 2006 18:55:44 -0500, Josh Stern wrote:Yep, that would be very useful. This feature, i.e. an ability to declare custom identifiers (or part of them) in templates, has been suggested before (not surprisingly). Lets hope that it will be implemented someday. *wink*wink* ;)mixin .FFoo!(a) x; // bring in the statement in the 'x' sub-namespaceThank you. This was the key information that I didn't pick up from the docs. It is documented but I didn't get it until now. The important passage from the docs is "A mixin has its own scope". I kept on reading that as "the mixin's template has its own scope" but now I understand it is the mixin statement itself that creates a new scope/namespace, and that the "MixinIdentifier" is the optional name one can give to that scope. Then one can use the MixinIdentifier as a namespace qualifier to disambiguate identifiers brought in by the mixin statements. Mind you, this would have been made easier if the 'alias' argument could also have been used to 'set' the identifier declared in the template. In other words it would have been 'smart' for mixin to allow ... template foo(alias a, alias b) { typeof(b) a(b) { . . . } } mixin foo!(Bar, 3); mixin foo!(Qwe, 3.14); to generate code as ... typeof(3) Bar(3) { . . . } typeof(3.14) Qwe(3.14) { . . . } then there would have been no disambiguation required.
Oct 06 2006