View mode: basic / threaded / horizontal-split · Log in · Help
October 18, 2002
Mixins
As I was doing my day job today, writing C++ code
and wishing it was D, I found myself once again wanting 
a feature that neither C++ nor D has.  What I want are 
mixins.  

You will find various explanations of mixins on the web
but to me they are just aggregation with a twist.  The
twist is that aggregated object has some access to the
object in which it is aggregated into.  

I think that with D's templates could be extended to
cover this feature.  My suggested syntax for this
would be.

template Mixin(this)
{
 int foo;

 int AccessAggObj(int a)
 {
   return this.ParentFunc() + foo + a;
 }
}


class UseMixin
{
 int ParentFunc()
 {
   return 12;
 }

 instance Mixin(this) bar;
 // foo and AccessAggObj are
 // made members of the class
 // accessible from bar;
}


UseMixin a = new UseMixin();

a.bar.foo = 5;

a.bar.AccessAggObj(7); // returns 24
October 19, 2002
Re: Mixins
Yes.  Wow.  That's alot like the C++ trick of inheriting from a template
that is parameterized with the derived class:

template <class Derived>
class Wierd
{
public:
   int Foo(int a)
   {
       return Derived::Bar(a+1)+4;
   }
};

class Wierder : public Wierd<Wierder>
{
public:
   void Test()
   {
       std::cout << Foo(3); // prints 5
   }
   int Bar(int b) { return b + 2; }
};

Voila!  Method overriding without vtables.  No virtual function table
necessary.  Call functions that only exist in your derived classes.

Why do you need abstract functions?  Just call a function on the derived
class and let the compiler try to figure it out.  If it can't it's an error.

It's a cool trick.  It could certainly use prettier syntax. But your thing
looks like it could be better possibly.

I would want mixins even if it's just inheriting a partial implementation
for an interface that is declared somewhere else.

I like interfaces.  But oftentimes you want to provide some default
implementation.  That's why I like multiple inheritance and mixins.
Otherwise you have to duplicate alot of interfaces (by hand, or cut and
paste) to accomplish the same thing.

Maybe it's more like an inherited "feature" that I want.  Exposing this
packaged feature that you get from somewhere else.  Maybe what I want is to
be able to have a class "merge" another class into itself.

class A
{
   int feature1;
}
class B
{
   int feature2;
   mixin A;
}
void Test()
{
   B b;
   printf(b.feature2);  // ok
   printf(b.feature1);  // ok also
}

Need some way to deal with name conflicts.  But this is almost essentially
Multiple Inheritance.  I could handle it if all conflicts were resolved with
that all of the conflicting declarations has to be abstract (the interface)
and only one must be an implementation.  MI so long as you promise the
compiler there will be no collisions.  If there are collisions you have to
rename something.  So it'd be mainly good for use inside a single component
where you can control use of it.  Not something you want to expose to the
outside world.

Sean

"Patrick Down" <pat@codemoon.com> wrote in message
news:Xns92ABA418CB124patcodemooncom@63.105.9.61...
>
> As I was doing my day job today, writing C++ code
> and wishing it was D, I found myself once again wanting
> a feature that neither C++ nor D has.  What I want are
> mixins.
>
> You will find various explanations of mixins on the web
> but to me they are just aggregation with a twist.  The
> twist is that aggregated object has some access to the
> object in which it is aggregated into.
>
> I think that with D's templates could be extended to
> cover this feature.  My suggested syntax for this
> would be.
>
> template Mixin(this)
> {
>   int foo;
>
>   int AccessAggObj(int a)
>   {
>     return this.ParentFunc() + foo + a;
>   }
> }
>
>
> class UseMixin
> {
>   int ParentFunc()
>   {
>     return 12;
>   }
>
>   instance Mixin(this) bar;
>   // foo and AccessAggObj are
>   // made members of the class
>   // accessible from bar;
> }
>
>
> UseMixin a = new UseMixin();
>
> a.bar.foo = 5;
>
> a.bar.AccessAggObj(7); // returns 24
October 19, 2002
Re: Mixins
"Sean L. Palmer" <seanpalmer@directvinternet.com> wrote in
news:aor45k$12of$1@digitaldaemon.com: 

> Yes.  Wow.  That's alot like the C++ trick of inheriting from a
> template that is parameterized with the derived class:

Yes.


> It's a cool trick.  It could certainly use prettier syntax. But your
> thing looks like it could be better possibly.
> 
> I would want mixins even if it's just inheriting a partial
> implementation for an interface that is declared somewhere else.
> 
> I like interfaces.  But oftentimes you want to provide some default
> implementation.  That's why I like multiple inheritance and mixins.
> Otherwise you have to duplicate alot of interfaces (by hand, or cut
> and paste) to accomplish the same thing.

OOP pays a lot of attention to the "is-a" type relations.  It's all
about creating abstract interfaces that allow specific objects to
be dealt with in a uniform manner.

I think perhaps there could be some advances made in dealing with
"has-a" type relationships.

I'm creating a car object.  It has an engine, wheels, body, 
transmission, etc...  I aggregate all these things into the car
object and then I spend time wiring together the various inputs
and output of the components to each other and the external car
interfaces.

Why can't there be some help with the wiring process?  Why can't 
an engine expect that it's container implements some sort of throttle 
control?  I see this as another sort of contract in a way.  To use an 
engine you must implement the correct set of inputs and output for it.

Anyway I see mixins as sort of a step in this direction.

> 
> Maybe it's more like an inherited "feature" that I want.  Exposing
> this packaged feature that you get from somewhere else.  Maybe what I
> want is to be able to have a class "merge" another class into itself.
> 
> class A
> {
>     int feature1;
> }
> class B
> {
>     int feature2;
>     mixin A;
> }
> void Test()
> {
>     B b;
>     printf(b.feature2);  // ok
>     printf(b.feature1);  // ok also
> }
> 
> Need some way to deal with name conflicts.  But this is almost
> essentially Multiple Inheritance.  I could handle it if all conflicts
> were resolved with that all of the conflicting declarations has to be
> abstract (the interface) and only one must be an implementation.  MI
> so long as you promise the compiler there will be no collisions.  If
> there are collisions you have to rename something.  So it'd be mainly
> good for use inside a single component where you can control use of
> it.  Not something you want to expose to the outside world.


With D, doing mixins with templates does away with the naming conflicts
and with all the associated problems with MI.  The naming conflicts
go away because the D templates require a instance identifier.  The MI
issues go away because code is not generated until the template is 
instanced in the class.
October 19, 2002
Re: Mixins
So you're advocating generics as being a suitable replacement for MI?

Mayhap...  must think about it.

Sean

"Patrick Down" <pat@codemoon.com> wrote in message
news:Xns92AC99CCA95D8patcodemooncom@63.105.9.61...
> "Sean L. Palmer" <seanpalmer@directvinternet.com> wrote in
> news:aor45k$12of$1@digitaldaemon.com:
>
> > Yes.  Wow.  That's alot like the C++ trick of inheriting from a
> > template that is parameterized with the derived class:
>
> Yes.
>
>
> > It's a cool trick.  It could certainly use prettier syntax. But your
> > thing looks like it could be better possibly.
> >
> > I would want mixins even if it's just inheriting a partial
> > implementation for an interface that is declared somewhere else.
> >
> > I like interfaces.  But oftentimes you want to provide some default
> > implementation.  That's why I like multiple inheritance and mixins.
> > Otherwise you have to duplicate alot of interfaces (by hand, or cut
> > and paste) to accomplish the same thing.
>
> OOP pays a lot of attention to the "is-a" type relations.  It's all
> about creating abstract interfaces that allow specific objects to
> be dealt with in a uniform manner.
>
> I think perhaps there could be some advances made in dealing with
> "has-a" type relationships.
>
> I'm creating a car object.  It has an engine, wheels, body,
> transmission, etc...  I aggregate all these things into the car
> object and then I spend time wiring together the various inputs
> and output of the components to each other and the external car
> interfaces.
>
> Why can't there be some help with the wiring process?  Why can't
> an engine expect that it's container implements some sort of throttle
> control?  I see this as another sort of contract in a way.  To use an
> engine you must implement the correct set of inputs and output for it.
>
> Anyway I see mixins as sort of a step in this direction.
>
> >
> > Maybe it's more like an inherited "feature" that I want.  Exposing
> > this packaged feature that you get from somewhere else.  Maybe what I
> > want is to be able to have a class "merge" another class into itself.
> >
> > class A
> > {
> >     int feature1;
> > }
> > class B
> > {
> >     int feature2;
> >     mixin A;
> > }
> > void Test()
> > {
> >     B b;
> >     printf(b.feature2);  // ok
> >     printf(b.feature1);  // ok also
> > }
> >
> > Need some way to deal with name conflicts.  But this is almost
> > essentially Multiple Inheritance.  I could handle it if all conflicts
> > were resolved with that all of the conflicting declarations has to be
> > abstract (the interface) and only one must be an implementation.  MI
> > so long as you promise the compiler there will be no collisions.  If
> > there are collisions you have to rename something.  So it'd be mainly
> > good for use inside a single component where you can control use of
> > it.  Not something you want to expose to the outside world.
>
>
> With D, doing mixins with templates does away with the naming conflicts
> and with all the associated problems with MI.  The naming conflicts
> go away because the D templates require a instance identifier.  The MI
> issues go away because code is not generated until the template is
> instanced in the class.
>
January 19, 2003
Re: Mixins
Some thoughts about mixins based on my experience with the Smallworld Magik
language:

Magik uses mixins as a major and very powerful feature. However it can lead to a
form of confusion that is best avoided. That is, a programmer devising a new
class looks thru a list of mixins and picks a few he thinks he needs, overrides
the functions he does not like, and adds what is missing. He now has a class
that without the mixins would have taken him a lot longer to write. However the
possibilities for laziness abound. If a class needs some functionality added,
just add a mixin; and this can go on and on. Adding is easy. Pruning out what is
not needed is the hard part.

Mixins tend to provide everything including the kitchen sink, ie far more than
is required in many cases, simply because they were written, with the best
intentions, for maximum flexibility and usefulness. And all those functions you
don't use are sitting there waiting to confuse a maintenance programmer because
he may not have a clue as to which ones are surplus to requirements. Ones that
ought never to be called are still available. He cannot therefore just pull out
a few mixins that don't look important. He might cause unexpected problems at
run-time (which is when the linkages to mixin functions get automatically cached
on-demand, in Magik). In D, the same problem would occur at compile-time.

Magik allows multiple-inheritance. Though it is easy enough to do, out of
thousands of object classes, a mere handful have ever used it, and could be
rewritten to not do so. The availability of mixins made the use of
multiple-inheritance effectively unnecessary and, if this had been known when
the code base development began, the multiple-inheritance feature might well
have been removed from the compiler.
Top | Discussion index | About this forum | D home