Jump to page: 1 2
Thread overview
mixin troubles
Oct 03, 2006
Derek Parnell
Oct 04, 2006
Derek Parnell
Oct 04, 2006
Derek Parnell
Oct 05, 2006
Josh Stern
Oct 05, 2006
Derek Parnell
Oct 05, 2006
Josh Stern
Oct 06, 2006
Derek Parnell
Oct 06, 2006
Josh Stern
Oct 06, 2006
Kristian
October 03, 2006
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
October 04, 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.


October 04, 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...
> 
>> 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:

Thanks for patience.

>  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.

>> 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.

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 PM
October 04, 2006
Derek Parnell wrote:
> 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...
>>
>>
>>>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:
> 
> 
> Thanks for patience.
>  
> 
>> 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.
>>

I may be wrong, but I think you could do this:
# mixin .Foo!(a).Foo  y ;
# mixin .Foo!(b).Foo  z ;
# assert(y() == 3);
# assert(z() == 3.14);

-- Chris Nicholson-Sauls
October 04, 2006
On Wed, 04 Oct 2006 01:55:45 -0500, Chris Nicholson-Sauls wrote:

> Derek Parnell wrote:
>> 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...
>>>
>>>
>>>>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:
>> 
>> Thanks for patience.
>> 
>> 
>>> 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.
>>>
> 
> I may be wrong, but I think you could do this:
> # mixin .Foo!(a).Foo  y ;
> # mixin .Foo!(b).Foo  z ;
> # assert(y() == 3);
> # assert(z() == 3.14);
> 

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 PM
October 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 defined

Almost, 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.


October 05, 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:
>>> 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...
>>>>
>>>>
>>>>>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:
>>> 
>>> Thanks for patience.
>>> 
>>> 
>>>> 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.
>>>>
>> 
>> I may be wrong, but I think you could do this:
>> # mixin .Foo!(a).Foo  y ;
>> # mixin .Foo!(b).Foo  z ;
>> # assert(y() == 3);
>> # assert(z() == 3.14);
>> 
> 
> 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

October 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!"
October 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:
> 
>> 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.

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());
}



> 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.
October 06, 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-namespace

Thank 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
« First   ‹ Prev
1 2