www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Mixins, alias parameters, and alias template instantiations

reply Reiner Pope <reiner.pope REMOVE.THIS.gmail.com> writes:
I find it rather frustrating that D seems like it should be able to do 
what I want, but somehow it can't.

One common form of boilerplate code that mixins seem like a good 
candidate for is properties -- especially getters. So, I tried to write 
mixins that made this less work (like Ruby's attr_reader). Basically, I 
was hoping that we could mix in and rename a function, but the renaming 
bit doesn't seem to work. Here's what I tried:

template getter(alias val)
{
         typeof(val) getter() { return val; }
}

class Foo
{
         int a;
         mixin getter!(a) bar;
         alias getter!(a) foo; // Fails with error message 1 below.

         unittest
         {
             Foo f = new Foo();
             writefln(f.getter()); // This works, but it isn't what I want
             writefln(f.foo()); // I want the property to appear like this
             writefln(f.bar()); // Or this, but this gives errors 2 and 3.
             // And of course, f.foo() doesn't exist since it couldn't 
be alias'ed in.
         }
}

Error messages:
1. template instance cannot use local 'a' as template parameter
2. undefined identifier (f dotexp mixin getter!(a);
).opCall
3. function expected before (), not (f dotexp mixin getter!(a);
).opCall of type void

I can understand why the alias instantiation fails, and I understand 
that the following would achieve what I want:

mixin getter!(a) _g;
alias _g.getter bar;

but that then means two lines of code, and namespace pollution, for what 
should really be a trivial task.

What I would like is, just like for normal templates, a single item 
would be an Implicit Template Property, and could thus be renamed. This 
would just be a special syntactical shorthand for single elements, such 
as the case I described here.

I hope you like it.

Cheers,

Reiner
Sep 18 2006
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Reiner Pope wrote:
 I find it rather frustrating that D seems like it should be able to do 
 what I want, but somehow it can't.
 
 One common form of boilerplate code that mixins seem like a good 
 candidate for is properties -- especially getters. So, I tried to write 
 mixins that made this less work (like Ruby's attr_reader). Basically, I 
 was hoping that we could mix in and rename a function, but the renaming 
 bit doesn't seem to work. Here's what I tried:
 
 template getter(alias val)
 {
         typeof(val) getter() { return val; }
 }
 
 class Foo
 {
         int a;
         mixin getter!(a) bar;
         alias getter!(a) foo; // Fails with error message 1 below.
 
         unittest
         {
             Foo f = new Foo();
             writefln(f.getter()); // This works, but it isn't what I want
             writefln(f.foo()); // I want the property to appear like this
             writefln(f.bar()); // Or this, but this gives errors 2 and 3.
             // And of course, f.foo() doesn't exist since it couldn't be 
 alias'ed in.
         }
 }
 
 Error messages:
 1. template instance cannot use local 'a' as template parameter
 2. undefined identifier (f dotexp mixin getter!(a);
 ).opCall
 3. function expected before (), not (f dotexp mixin getter!(a);
 ).opCall of type void
 
 I can understand why the alias instantiation fails, and I understand 
 that the following would achieve what I want:
 
 mixin getter!(a) _g;
 alias _g.getter bar;
 
 but that then means two lines of code, and namespace pollution, for what 
 should really be a trivial task.
 
 What I would like is, just like for normal templates, a single item 
 would be an Implicit Template Property, and could thus be renamed. This 
 would just be a special syntactical shorthand for single elements, such 
 as the case I described here.
 
 I hope you like it.
 
 Cheers,
 
 Reiner

The following will accomplish what you want, even if it is slightly counter-intuitive. # import std .stdio ; # # template MGettor (alias Fld) { # typeof(Fld) opCall () { # return Fld; # } # } # # class Foo { # int a = 1 , # b = 2 ; # # mixin MGettor!(a) getA ; # mixin MGettor!(b) getB ; # } # # void main () { # auto foo = new Foo; # # writefln(foo.getA()); # writefln(foo.getB()); # } Caveat: Forget the parentheses when calling the gettor, and you get an ICE. Eek. (Breaks properties syntax, therefore.) -- Chris Nicholson-Sauls
Sep 18 2006
parent Reiner Pope <reiner.pope REMOVE.THIS.gmail.com> writes:
It's a clever idea, but this:
 Caveat: Forget the parentheses when calling the gettor, and you get an 
 ICE.  Eek.  (Breaks properties syntax, therefore.)

property syntax is a big cost for me. I'm still hoping for an explicit property syntax, which should hopefully clear up all of these problems... Cheers, Reiner
Sep 18 2006