Thread overview
Mixins, alias parameters, and alias template instantiations
Sep 18, 2006
Reiner Pope
Sep 19, 2006
Reiner Pope
September 18, 2006
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
September 18, 2006
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
September 19, 2006
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.)
kills it for me. I was looking for automatic properties, so losing the 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