www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Cumbersome overloading of mixed-in functions

reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
Say I want to add a bunch of (virtual) methods to a class.  All these 
methods do very similar things, just on different types.  Hmm, sounds like a 
job for a template.

So I write up a templated version of the method:

template FuncTemplate(T)
{
    void func(T val)
    {
        // do some stuff with val
    }
}

Now I can mix it into the class.  I have, no joke, about 10 or 15 types I 
want to mix this in as.  So I do this:

class Foo
{
    mixin FuncTemplate!(int);
    mixin FuncTemplate!(float);
}

Oh crap, I can't even go any further right now.  If I try to instantiate the 
class and call these methods:

Foo f = new Foo();
f.func(5);

I get the error:

function blah.Foo.FuncTemplate!(int).func conflicts with 
blah.Foo.FuncTemplate!(float).func at..

I look up in the spec, and find that it's possible to overload these 
functions, but it has to be done manually, using dummy mixin names and then 
aliasing them:

class Foo
{
    mixin FuncTemplate!(int) intFunc;
    mixin FuncTemplate!(float) floatFunc;

    alias intFunc.func func;
    alias floatFunc.func func;
}

Foo f = new Foo();
f.func(5); // yay, works

Now for the other 12 or 13 types, which means lots of namespace pollution in 
my class for all the dummy mixin names, and a matching alias for each mixin. 
And -- oh yeah, I've got 4 or 5 other methods which I want to be templated 
for the same set of types!

At which point my class degenerates into four pages of mixins and aliases. 
I might as well just copy-and-paste the functions and change the parameter 
type; it'd be a lot clearer.

What a mess.  There has to be a better way to do this.  I'm thinking 
something like

mixin func = FuncTemplate!(int).func;
mixin func = FuncTemplate!(float).func;

Kind of an all-in-one mixin/alias without any dummy names, and with a syntax 
similar to import renaming (and, in effect, a sort of similar effect).

Or, maybe mixin scoping could be changed so that unnamed mixins have their 
symbols imported into the local namespace.  After all, if you write:

mixin FuncTemplate!(int);
mixin FuncTemplate!(float);

..

f.func(4); // error, ambiguous - in both !(int) and !(float)

There is _no way_ to disambiguate it unless you use a named mixin - so why 
bother making it ambiguous with unnamed mixins?

Although I see this second proposal as a problem with:

template Temp(T)
{
    T x;
}

mixin Temp!(int);
mixin Temp!(float);

..

writefln(x); // ? ambiguous

Although in this case, I would imagine the normal variable declaration 
semantics would kick in and say that you were redefining x with the !(float) 
mixin. 
Aug 19 2006
parent reply kris <foo bar.com> writes:
Jarrett Billingsley wrote:
 Say I want to add a bunch of (virtual) methods to a class.  All these 
 methods do very similar things, just on different types.  Hmm, sounds like a 
 job for a template.
 
 So I write up a templated version of the method:
 
 template FuncTemplate(T)
 {
     void func(T val)
     {
         // do some stuff with val
     }
 }
 
 Now I can mix it into the class.  I have, no joke, about 10 or 15 types I 
 want to mix this in as.  So I do this:
 
 class Foo
 {
     mixin FuncTemplate!(int);
     mixin FuncTemplate!(float);
 }
 
 Oh crap, I can't even go any further right now.  If I try to instantiate the 
 class and call these methods:
 
 Foo f = new Foo();
 f.func(5);
 
 I get the error:
 
 function blah.Foo.FuncTemplate!(int).func conflicts with 
 blah.Foo.FuncTemplate!(float).func at..
 
 I look up in the spec, and find that it's possible to overload these 
 functions, but it has to be done manually, using dummy mixin names and then 
 aliasing them:
 
 class Foo
 {
     mixin FuncTemplate!(int) intFunc;
     mixin FuncTemplate!(float) floatFunc;
 
     alias intFunc.func func;
     alias floatFunc.func func;
 }
 
 Foo f = new Foo();
 f.func(5); // yay, works
 
 Now for the other 12 or 13 types, which means lots of namespace pollution in 
 my class for all the dummy mixin names, and a matching alias for each mixin. 
 And -- oh yeah, I've got 4 or 5 other methods which I want to be templated 
 for the same set of types!
 
 At which point my class degenerates into four pages of mixins and aliases. 
 I might as well just copy-and-paste the functions and change the parameter 
 type; it'd be a lot clearer.
 
 What a mess.  There has to be a better way to do this.  I'm thinking 
 something like
 
 mixin func = FuncTemplate!(int).func;
 mixin func = FuncTemplate!(float).func;
 
 Kind of an all-in-one mixin/alias without any dummy names, and with a syntax 
 similar to import renaming (and, in effect, a sort of similar effect).
 
 Or, maybe mixin scoping could be changed so that unnamed mixins have their 
 symbols imported into the local namespace.  After all, if you write:
 
 mixin FuncTemplate!(int);
 mixin FuncTemplate!(float);
 
 ..
 
 f.func(4); // error, ambiguous - in both !(int) and !(float)
 
 There is _no way_ to disambiguate it unless you use a named mixin - so why 
 bother making it ambiguous with unnamed mixins?
 
 Although I see this second proposal as a problem with:
 
 template Temp(T)
 {
     T x;
 }
 
 mixin Temp!(int);
 mixin Temp!(float);
 
 ..
 
 writefln(x); // ? ambiguous
 
 Although in this case, I would imagine the normal variable declaration 
 semantics would kick in and say that you were redefining x with the !(float) 
 mixin. 
 
 
Better to do it all manually and save yourself the grief. Mixin should perhaps be removed from the language until such time that it works in a reasonable manner :(
Aug 19 2006
parent reply nobody <nobody mailinator.com> writes:
kris wrote:
 Jarrett Billingsley wrote:
 Say I want to add a bunch of (virtual) methods to a class.  All these 
 methods do very similar things, just on different types.  Hmm, sounds 
 like a job for a template.
Better to do it all manually and save yourself the grief. Mixin should perhaps be removed from the language until such time that it works in a reasonable manner :(
Just a little while ago I posed a question to D.learn about implementing all the permutations possible of RGB, HSL, RGBA and HSLA. The numbers from that post: 3! + 3! + 4! + 4! = 60 types (3! + 3! + 4! + 4!)^2 = 3600 opAssigns Certainly manually is not really an option here.
Aug 20 2006
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
nobody wrote:
 kris wrote:
 
 Jarrett Billingsley wrote:

 Say I want to add a bunch of (virtual) methods to a class.  All these 
 methods do very similar things, just on different types.  Hmm, sounds 
 like a job for a template.
Better to do it all manually and save yourself the grief. Mixin should perhaps be removed from the language until such time that it works in a reasonable manner :(
Just a little while ago I posed a question to D.learn about implementing all the permutations possible of RGB, HSL, RGBA and HSLA. The numbers from that post: 3! + 3! + 4! + 4! = 60 types (3! + 3! + 4! + 4!)^2 = 3600 opAssigns Certainly manually is not really an option here.
Right now, in cases such as this, the best option seems to be writing a simple source generator to cough up the code into a file. Usually the time/energy spent writing the generator program is reasonably less than manually typing them all out. -- Chris Nicholson-Sauls
Aug 20 2006
parent Kristian <kjkilpi gmail.com> writes:
On Sun, 20 Aug 2006 11:40:24 +0300, Chris Nicholson-Sauls  =

<ibisbasenji gmail.com> wrote:

 nobody wrote:
 kris wrote:

 Jarrett Billingsley wrote:

 Say I want to add a bunch of (virtual) methods to a class.  All the=
se =
 methods do very similar things, just on different types.  Hmm, soun=
ds =
 like a job for a template.
Better to do it all manually and save yourself the grief. Mixin shou=
ld =
 perhaps be removed from the language until such time that it works i=
n =
 a reasonable manner :(
Just a little while ago I posed a question to D.learn about =
 implementing all the permutations possible of RGB, HSL, RGBA and HSLA=
. =
 The numbers from that post:
      3! + 3! + 4! + 4! =3D 60 types
    (3! + 3! + 4! + 4!)^2 =3D 3600 opAssigns
  Certainly manually is not really an option here.
Right now, in cases such as this, the best option seems to be writing =
a =
 simple source generator to cough up the code into a file.  Usually the=
=
 time/energy spent writing the generator program is reasonably less tha=
n =
 manually typing them all out.

 -- Chris Nicholson-Sauls
Hmm, why the mixin does not simply generate/add the code, which is then = = compiled normally with the original code? Similarly like macros work in = = C/C++. This way there would be no naming conficts with function overload= s = as Jarrett described earlier, for instance. The compiler knows when it = compiles the mixin code so the corresponging error messages can be = generated, etc. I would very much like to see mixins working properly. It would be a gre= at = asset for D if there were a good code generator ability!
Aug 20 2006