www.digitalmars.com         C & C++   DMDScript  

D - COMMENTS: Mixins Specification

reply "fred" <info fleet-manage.com> writes:
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

I would like to proposed the following specification for Mixins be =
included as part of Version 1.0=20
D Programming Language specification. All comments are welcomed.

MIXINS SPECIFICATION      Version 0.1

Introduction
What are mixins ?
A mixin is a class-like entity whose methods/fields are mixed-in to the =
mixing class just=20
as if the author of that class had written them manually.
As Matthew so neatly put it (see =
D/28348 )

Why do we need them ?
The rational for Mixins is quite compelling...
One of the greatest shortcomings of the C++ language from a Object =
Oriented perspective,=20
is that there is no language support for Aggregated Objects. As such, =
Aggregation has to be=20
performed programatically, often (incorrectly) using the inheritance =
mechanism as a coding=20
shortcut. By including language support we provide a direct correlation =
between OOD using=20
modeling techniques like UML, and OOP.

Background
Please read the following;
D/28455
D/28511
D/28553

Lexical
I propose that we use one of the two remaining (common) symbols, i.e. # =
and   as well as=20
the keyword mixin. For this document we'll use # as the mixin symbol

Syntax
There are a number of syntax alternatives that could be incorporated.

Alternative A:
class <identifier> [: <inherited-class>]
                   [# <aggregated-class> <local-identifier>]*=20

For example;
class Lamp : Light
           # Body      cBody      =20
           # Switch    cSwitch
           # Globe     cGlobe=20
           # PowerCord cPowerCord
{
    this() {
        super();                    =20
        cBody();                     // Body construction
        cGlobe();                    // Globe construction
        cPowerCord();                // PowerCord construction
        cSwitch(cGlobe,cPowerCord);  // Switch construction
    }
};

Alternative B:
class <identifier> [: <inherited-class>]
                   [# <aggregated-class> <local-identifier>=20
                   [, <aggregated-class> <local-identifier>]*]=20

For example;

class Lamp : Light
           # Body      cBody=20
           , Switch    cSwitch=20
           , Globe     cGlobe=20
           , PowerCord cPowerCord
{
    this() {
        super();
        cBody();                     // Body construction
        cGlobe();                    // Globe construction
        cPowerCord();                // PowerCord construction
        cSwitch(cGlobe,cPowerCord);  // Switch construction
    }
};

Semantics
The rules for Mixin variables should be the same as class member =
declarations, except
Mixins allow the interfaces of the aggregated class to be included as =
part of the mixing class.
This fact means that it is possible to have multiple versions of the =
same member name=20
within a mixing class.

I propose a simple precedence rule, where the member defined in the =
class overrides those=20
defined in the aggregated class, and those in the aggregated classes are =
assigned according=20
to the order they are declared. If this was to take place, a compiler =
warning message stating=20
"that member X of aggregated class A is taking precedence over that in =
aggregated class B"=20
should be displayed in the error log.

Note: there are probably other things that will need to be considered =
here !

Conclusion
Mixins permit externally declare classes to be used as part of a class, =
and in so doing provides
a real alternative to the Multiple Inheritance option provided for in =
the C++ language. As such, this=20
relatively insignificant addition to the language should greatly enhance =
the overall flexibility of the=20
D Programming Language.=20

Comments !
Apr 29 2004
next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
fred wrote:

 I would like to proposed the following specification for Mixins be 
 included as part of Version 1.0
 D Programming Language specification. /All comments are welcomed./

I added this to http://www.prowiki.org/wiki4d/wiki.cgi?FeatureRequestList/Mixins. -- -Anderson: http://badmama.com.au/~anderson/
Apr 29 2004
prev sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
Wow, I hadn't realised that this had got so serious!

I've been chatting with Walter about a mixins syntax to serve the needs of DTL,
but had (carelessly / selfishly / stupidly / ...) not put it up on the group, as
I didn't have time for a debate (which I still don't).

Roughly, here's my proposal, which, at first glance, appears to be quite a
different kettle of fish to what you're talking about:

// - Mixins define class/instance methods.
// - Mixins do not define *any* instance fields. (Not sure about static fields -
what do you think?)
// - Mixin methods are added into the mixing class as if the user had typed them
in
// - Mixins have *no* polymorphic aspects whatsoever. Two classes that each mix
//   the same mixin are nonetheless completely unrelated
// - Mixin methods may "become" polymorphic with respect to any interface(s)
that
the mixing class is "implement"ing
// - If the mixing class already contains a method of the same signature, that
"overrides" - prevents incorporation - of that mixin method.

Syntax:

mixin Ranges(C) // C is the mixing class.
{
private:
    typedef C.value_type    value_type; // A convenience for the mixin
implementation, and also a constraint on C
    typedef C.index_type    index_type; // A convenience for the mixin
implementation, and also a constraint on C

public:
    boolean contains(value_type comperand)
    {
        foreach(value_type v; cast(C)(this)) // How to get to the real, gestalt,
entity. foreach acts as a constraint on C
        {
            if(v == comperand)
            {
                return cast(boolean)(true);
            }
        }

        return cast(boolean)(false);
    }

    . . .
}

And is used as follows (as in the DTL classes, which require only that the
mixing
class has value_type and index_type member types, and be freachable):

template List(T, B = EmptyBase)
{
    public class List
        : B                      // base class
        , mixes Ranges    // Note: do not need to specify mixing class, since it
cannot be ambiguous.
    {
    }
}

Note that a mixin could also be a template, but needn't be. In a sense, it's
already a template, as it's parameterised by one (and only one) type, its mixing
class.

Clearly, there are some differences between your proposal and mine:

minor:

- I don't like the syntax you propose (i.e. the #,  ), but this is a pretty
minor
issue, and will be whatever Walter deems most unambiguous and easy to parse

major:

- you allow for mixins to provide fields
- you allow mixins to introduce a different polymorphic nature to their mixing
class
- you allow mixins to have constructors, which I do not

I disagree with all of these, since it seems that your mixin design is almost a
halfway house between SI and MI and, although I understand the motivation, I
think we'll be in murky territory.

Of course, my perspective may well be covered by my needs. ;)

Matthew



"fred" <info fleet-manage.com> wrote in message
news:c6s9ck$7go$1 digitaldaemon.com...
I would like to proposed the following specification for Mixins be included as
part of Version 1.0
D Programming Language specification. All comments are welcomed.

MIXINS SPECIFICATION      Version 0.1

Introduction
What are mixins ?
A mixin is a class-like entity whose methods/fields are mixed-in to the mixing
class just
as if the author of that class had written them manually.
As Matthew so neatly put it (see
D/28348 )

Why do we need them ?
The rational for Mixins is quite compelling...
One of the greatest shortcomings of the C++ language from a Object Oriented
perspective,
is that there is no language support for Aggregated Objects. As such,
Aggregation
has to be
performed programatically, often (incorrectly) using the inheritance mechanism
as
a coding
shortcut. By including language support we provide a direct correlation between
OOD using
modeling techniques like UML, and OOP.

Background
Please read the following;
D/28455
D/28511
D/28553

Lexical
I propose that we use one of the two remaining (common) symbols, i.e. # and   as
well as
the keyword mixin. For this document we'll use # as the mixin symbol

Syntax
There are a number of syntax alternatives that could be incorporated.

Alternative A:
class <identifier> [: <inherited-class>]
                   [# <aggregated-class> <local-identifier>]*

For example;
class Lamp : Light
           # Body      cBody
           # Switch    cSwitch
           # Globe     cGlobe
           # PowerCord cPowerCord
{
    this() {
        super();
        cBody();                     // Body construction
        cGlobe();                    // Globe construction
        cPowerCord();                // PowerCord construction
        cSwitch(cGlobe,cPowerCord);  // Switch construction
    }
};

Alternative B:
class <identifier> [: <inherited-class>]
                   [# <aggregated-class> <local-identifier>
                   [, <aggregated-class> <local-identifier>]*]

For example;

class Lamp : Light
           # Body      cBody
           , Switch    cSwitch
           , Globe     cGlobe
           , PowerCord cPowerCord
{
    this() {
        super();
        cBody();                     // Body construction
        cGlobe();                    // Globe construction
        cPowerCord();                // PowerCord construction
        cSwitch(cGlobe,cPowerCord);  // Switch construction
    }
};

Semantics
The rules for Mixin variables should be the same as class member declarations,
except
Mixins allow the interfaces of the aggregated class to be included as part of
the
mixing class.
This fact means that it is possible to have multiple versions of the same member
name
within a mixing class.

I propose a simple precedence rule, where the member defined in the class
overrides those
defined in the aggregated class, and those in the aggregated classes are
assigned
according
to the order they are declared. If this was to take place, a compiler warning
message stating
"that member X of aggregated class A is taking precedence over that in
aggregated
class B"
should be displayed in the error log.

Note: there are probably other things that will need to be considered here !

Conclusion
Mixins permit externally declare classes to be used as part of a class, and in
so
doing provides
a real alternative to the Multiple Inheritance option provided for in the C++
language. As such, this
relatively insignificant addition to the language should greatly enhance the
overall flexibility of the
D Programming Language.

Comments !
Apr 29 2004
next sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Matthew wrote:

 Wow, I hadn't realised that this had got so serious!
 
 I've been chatting with Walter about a mixins syntax to serve the needs of DTL,
 but had (carelessly / selfishly / stupidly / ...) not put it up on the group,
as
 I didn't have time for a debate (which I still don't).
 
 Roughly, here's my proposal, which, at first glance, appears to be quite a
 different kettle of fish to what you're talking about:
 
 // - Mixins define class/instance methods.
 // - Mixins do not define *any* instance fields. (Not sure about static fields
-
 what do you think?)
 // - Mixin methods are added into the mixing class as if the user had typed
them
 in
 // - Mixins have *no* polymorphic aspects whatsoever. Two classes that each mix
 //   the same mixin are nonetheless completely unrelated
 // - Mixin methods may "become" polymorphic with respect to any interface(s)
that
 the mixing class is "implement"ing
 // - If the mixing class already contains a method of the same signature, that
 "overrides" - prevents incorporation - of that mixin method.

I like it. It is simple and exactly what you need to put mixins to good use. Especially the fact that it doesn't change the classes type will prevent a lot of headaches. One other thing may be important, though. I think mixins should be combinable to form new mixins (i.e. some kind of multiple inheritance between mixins but without any type issues). I mostly want mixins to be able to conveniently provide default implementations for interfaces. And since interfaces form a hierarchy, the implementations of more specialized interfaces could then re-use implementations of the general interfaces. The implementation shouldn't be much of a problem since mixins are "typeless", so there can be none of that multiple inheritance chaos we know from C++. It would be the same as simply copying all the code from the different mixins into a new mixin, but allowing the newly created mixin to overwrite methods already defined in one of the base mixins. Note that this simply means that mixins can mix-in other mixins in the same way that classes can. Example: mixin A(X) {...} mixin B(X) {...} mixin C(X) mixes A,B {...}
Apr 30 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message
news:c6t7gs$1m30$1 digitaldaemon.com...
 Matthew wrote:

 Wow, I hadn't realised that this had got so serious!

 I've been chatting with Walter about a mixins syntax to serve the needs of


 but had (carelessly / selfishly / stupidly / ...) not put it up on the group,


 I didn't have time for a debate (which I still don't).

 Roughly, here's my proposal, which, at first glance, appears to be quite a
 different kettle of fish to what you're talking about:

 // - Mixins define class/instance methods.
 // - Mixins do not define *any* instance fields. (Not sure about static


 what do you think?)
 // - Mixin methods are added into the mixing class as if the user had typed


 in
 // - Mixins have *no* polymorphic aspects whatsoever. Two classes that each


 //   the same mixin are nonetheless completely unrelated
 // - Mixin methods may "become" polymorphic with respect to any interface(s)


 the mixing class is "implement"ing
 // - If the mixing class already contains a method of the same signature,


 "overrides" - prevents incorporation - of that mixin method.

I like it. It is simple and exactly what you need to put mixins to good use. Especially the fact that it doesn't change the classes type will prevent a lot of headaches. One other thing may be important, though. I think mixins should be combinable to form new mixins (i.e. some kind of multiple inheritance between mixins but without any type issues). I mostly want mixins to be able to conveniently provide default implementations for interfaces. And since interfaces form a hierarchy, the implementations of more specialized interfaces could then re-use implementations of the general interfaces. The implementation shouldn't be much of a problem since mixins are "typeless", so there can be none of that multiple inheritance chaos we know from C++. It would be the same as simply copying all the code from the different mixins into a new mixin, but allowing the newly created mixin to overwrite methods already defined in one of the base mixins. Note that this simply means that mixins can mix-in other mixins in the same way that classes can. Example: mixin A(X) {...} mixin B(X) {...} mixin C(X) mixes A,B {...}

That seems reasonable, except where they had methods with the same signatures. I don't like the DAG crap that would transpire as a result.
Apr 30 2004
parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Matthew wrote:
Note that this simply means that mixins can mix-in other mixins in the
same way that classes can.

Example:

mixin A(X) {...}
mixin B(X) {...}

mixin C(X) mixes A,B {...}

That seems reasonable, except where they had methods with the same signatures. I don't like the DAG crap that would transpire as a result.

I think the same rules that are used when a class uses multiple mixins should apply. How is it handled there? The optimal thing would be if such conflicts are silently ignored if the function's code is the same in all mixins. Might be a little complicated to implement though (or it may be a simple memcmp - probably only Walter knows). Otherwise I see two solutions: 1) it is an error and the class must override such functions 2) use a simple precedence rule, like first mixin wins (according to the order in which they are mentioned in the class definition). I like this one because of its simplicity. One could argue that it can hide mistakes, but it is basically the same thing as the rule that class methods win over mixin methods. I.e. "read the class definition from left to right and use the first matching method you find in the mentioned entities". Hauke
Apr 30 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message
news:c6tuu6$2ukn$1 digitaldaemon.com...
 Matthew wrote:
Note that this simply means that mixins can mix-in other mixins in the
same way that classes can.

Example:

mixin A(X) {...}
mixin B(X) {...}

mixin C(X) mixes A,B {...}

That seems reasonable, except where they had methods with the same


 don't like the DAG crap that would transpire as a result.

I think the same rules that are used when a class uses multiple mixins should apply. How is it handled there? The optimal thing would be if such conflicts are silently ignored if the function's code is the same in all mixins. Might be a little complicated to implement though (or it may be a simple memcmp - probably only Walter knows). Otherwise I see two solutions: 1) it is an error and the class must override such functions

Of course! Perfect! All we need is a way to say "super" for a given mixin.
 2) use a simple precedence rule, like first mixin wins (according to the
 order in which they are mentioned in the class definition). I like this
 one because of its simplicity. One could argue that it can hide
 mistakes, but it is basically the same thing as the rule that class
 methods win over mixin methods. I.e. "read the class definition from
 left to right and use the first matching method you find in the
 mentioned entities".

Too complex and easy to get wrong.
Apr 30 2004
parent Hauke Duden <H.NS.Duden gmx.net> writes:
Matthew wrote:
Note that this simply means that mixins can mix-in other mixins in the
same way that classes can.

Example:

mixin A(X) {...}
mixin B(X) {...}

mixin C(X) mixes A,B {...}

That seems reasonable, except where they had methods with the same

1) it is an error and the class must override such functions

Of course! Perfect! All we need is a way to say "super" for a given mixin.

Well, if A is the mixin whose "foo" you want to call, then the syntax A.foo() comes to mind ;). Hauke
Apr 30 2004
prev sibling next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Matthew wrote:

Wow, I hadn't realised that this had got so serious!

I've been chatting with Walter about a mixins syntax to serve the needs of DTL,
but had (carelessly / selfishly / stupidly / ...) not put it up on the group, as
I didn't have time for a debate (which I still don't).

Roughly, here's my proposal, which, at first glance, appears to be quite a
different kettle of fish to what you're talking about:

// - Mixins define class/instance methods.
// - Mixins do not define *any* instance fields. (Not sure about static fields -
what do you think?)
// - Mixin methods are added into the mixing class as if the user had typed them
in
// - Mixins have *no* polymorphic aspects whatsoever. Two classes that each mix
//   the same mixin are nonetheless completely unrelated
// - Mixin methods may "become" polymorphic with respect to any interface(s)
that
the mixing class is "implement"ing
// - If the mixing class already contains a method of the same signature, that
"overrides" - prevents incorporation - of that mixin method.

Syntax:

mixin Ranges(C) // C is the mixing class.
{
private:
    typedef C.value_type    value_type; // A convenience for the mixin
implementation, and also a constraint on C
    typedef C.index_type    index_type; // A convenience for the mixin
implementation, and also a constraint on C

public:
    boolean contains(value_type comperand)
    {
        foreach(value_type v; cast(C)(this)) // How to get to the real, gestalt,
entity. foreach acts as a constraint on C
        {
            if(v == comperand)
            {
                return cast(boolean)(true);
            }
        }

        return cast(boolean)(false);
    }

    . . .
}

And is used as follows (as in the DTL classes, which require only that the
mixing
class has value_type and index_type member types, and be freachable):

template List(T, B = EmptyBase)
{
    public class List
        : B                      // base class
        , mixes Ranges    // Note: do not need to specify mixing class, since it
cannot be ambiguous.
    {
    }
}

Note that a mixin could also be a template, but needn't be. In a sense, it's
already a template, as it's parameterised by one (and only one) type, its mixing
class.

Clearly, there are some differences between your proposal and mine:

minor:

- I don't like the syntax you propose (i.e. the #,  ), but this is a pretty
minor
issue, and will be whatever Walter deems most unambiguous and easy to parse

major:

- you allow for mixins to provide fields
- you allow mixins to introduce a different polymorphic nature to their mixing
class
- you allow mixins to have constructors, which I do not

I disagree with all of these, since it seems that your mixin design is almost a
halfway house between SI and MI and, although I understand the motivation, I
think we'll be in murky territory.

Of course, my perspective may well be covered by my needs. ;)

Matthew
  

Just out of interest: It appears to me that mixins (the class part) are very similar to structs? Why couldn't structs be used as mixins instead? I mean something like: struct Ranges(C) // C is the mixing class. { private: typedef C.value_type value_type; // A convenience for the mixin implementation, and also a constraint on C typedef C.index_type index_type; // A convenience for the mixin implementation, and also a constraint on C public: boolean contains(value_type comperand) { foreach(value_type v; cast(C)(this)) // How to get to the real, gestalt, entity. foreach acts as a constraint on C { if(v == comperand) { return cast(boolean)(true); } } return cast(boolean)(false); } . . . } template List(T, B = EmptyBase) { public class List : B // base class , mixes Ranges // Note: do not need to specify mixing class, since it cannot be ambiguous. { } } -- -Anderson: http://badmama.com.au/~anderson/
Apr 30 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:c6t9ri$1pfq$1 digitaldaemon.com...
 Matthew wrote:

Wow, I hadn't realised that this had got so serious!

I've been chatting with Walter about a mixins syntax to serve the needs of


but had (carelessly / selfishly / stupidly / ...) not put it up on the group,


I didn't have time for a debate (which I still don't).

Roughly, here's my proposal, which, at first glance, appears to be quite a
different kettle of fish to what you're talking about:

// - Mixins define class/instance methods.
// - Mixins do not define *any* instance fields. (Not sure about static


what do you think?)
// - Mixin methods are added into the mixing class as if the user had typed


in
// - Mixins have *no* polymorphic aspects whatsoever. Two classes that each


//   the same mixin are nonetheless completely unrelated
// - Mixin methods may "become" polymorphic with respect to any interface(s)


the mixing class is "implement"ing
// - If the mixing class already contains a method of the same signature, that
"overrides" - prevents incorporation - of that mixin method.

Syntax:

mixin Ranges(C) // C is the mixing class.
{
private:
    typedef C.value_type    value_type; // A convenience for the mixin
implementation, and also a constraint on C
    typedef C.index_type    index_type; // A convenience for the mixin
implementation, and also a constraint on C

public:
    boolean contains(value_type comperand)
    {
        foreach(value_type v; cast(C)(this)) // How to get to the real,


entity. foreach acts as a constraint on C
        {
            if(v == comperand)
            {
                return cast(boolean)(true);
            }
        }

        return cast(boolean)(false);
    }

    . . .
}

And is used as follows (as in the DTL classes, which require only that the


class has value_type and index_type member types, and be freachable):

template List(T, B = EmptyBase)
{
    public class List
        : B                      // base class
        , mixes Ranges    // Note: do not need to specify mixing class, since


cannot be ambiguous.
    {
    }
}

Note that a mixin could also be a template, but needn't be. In a sense, it's
already a template, as it's parameterised by one (and only one) type, its


class.

Clearly, there are some differences between your proposal and mine:

minor:

- I don't like the syntax you propose (i.e. the #,  ), but this is a pretty


issue, and will be whatever Walter deems most unambiguous and easy to parse

major:

- you allow for mixins to provide fields
- you allow mixins to introduce a different polymorphic nature to their mixing
class
- you allow mixins to have constructors, which I do not

I disagree with all of these, since it seems that your mixin design is almost


halfway house between SI and MI and, although I understand the motivation, I
think we'll be in murky territory.

Of course, my perspective may well be covered by my needs. ;)

Matthew

Just out of interest: It appears to me that mixins (the class part) are very similar to structs? Why couldn't structs be used as mixins instead?

Because a struct does not have a mixing class. If you made the struct a template, that would mean that mixins could not be templates - which they can in my proposal - because the "template" syntax would already be used in making it a mixin. There are several other reasons why it can't be so, but that's good enough.
 I mean something like:

 struct Ranges(C) // C is the mixing class.
 {
 private:
     typedef C.value_type    value_type; // A convenience for the mixin
 implementation, and also a constraint on C
     typedef C.index_type    index_type; // A convenience for the mixin
 implementation, and also a constraint on C

 public:
     boolean contains(value_type comperand)
     {
         foreach(value_type v; cast(C)(this)) // How to get to the real,

 entity. foreach acts as a constraint on C
         {
             if(v == comperand)
             {
                 return cast(boolean)(true);
             }
         }

         return cast(boolean)(false);
     }

     . . .
 }


 template List(T, B = EmptyBase)
 {
     public class List
         : B                      // base class
         , mixes Ranges    // Note: do not need to specify mixing class, since

 cannot be ambiguous.
     {
     }
 }


 -- 
 -Anderson: http://badmama.com.au/~anderson/

Apr 30 2004
parent J Anderson <REMOVEanderson badmama.com.au> writes:
Matthew wrote:

Just out of interest: It appears to me that mixins (the class part) are
very similar to structs?  Why couldn't structs be used as mixins instead?
    

Because a struct does not have a mixing class. If you made the struct a template, that would mean that mixins could not be templates - which they can in my proposal - because the "template" syntax would already be used in making it a mixin. There are several other reasons why it can't be so, but that's good enough.

-- -Anderson: http://badmama.com.au/~anderson/
Apr 30 2004
prev sibling next sibling parent reply Patrick Down <Patrick_member pathlink.com> writes:
In article <c6sb58$a39$1 digitaldaemon.com>, Matthew says...
Wow, I hadn't realised that this had got so serious!

I've been chatting with Walter about a mixins syntax to serve the needs of DTL,
but had (carelessly / selfishly / stupidly / ...) not put it up on the group, as
I didn't have time for a debate (which I still don't).

Real work has been keeping me busy for 14 days straight here but I will make a few comments.
Roughly, here's my proposal, which, at first glance, appears to be quite a
different kettle of fish to what you're talking about:

// - Mixins define class/instance methods.
// - Mixins do not define *any* instance fields. (Not sure about static fields -
what do you think?)

This seems a little arbitrary. Why should this restriction be made especially give the implementation just below. I can think of a number of reason to want fields.
// - Mixin methods are added into the mixing class as if the user had typed them
in

Yes
// - Mixins have *no* polymorphic aspects whatsoever. Two classes that each mix
//   the same mixin are nonetheless completely unrelated

Yes
// - Mixin methods may "become" polymorphic with respect to any interface(s)
that
the mixing class is "implement"ing
// - If the mixing class already contains a method of the same signature, that
"overrides" - prevents incorporation - of that mixin method.

Does this include methods from a base of the class? I would say that any directly defined members of the class take precedence over the mixin method but the mixin method take precedence over and base class method. My view point on mixins is in line with Fred's post. ( See my reply to him. ) The major difference is that I think the mixin declaration needs to go into the class body not the header. The reason for this is that I think mixins should be able to be able to be parameterized by items from the declaration scope.
Apr 30 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Patrick Down" <Patrick_member pathlink.com> wrote in message
news:c6ts0i$2pjn$1 digitaldaemon.com...
 In article <c6sb58$a39$1 digitaldaemon.com>, Matthew says...
Wow, I hadn't realised that this had got so serious!

I've been chatting with Walter about a mixins syntax to serve the needs of


but had (carelessly / selfishly / stupidly / ...) not put it up on the group,


I didn't have time for a debate (which I still don't).

Real work has been keeping me busy for 14 days straight here but I will make a few comments.
Roughly, here's my proposal, which, at first glance, appears to be quite a
different kettle of fish to what you're talking about:

// - Mixins define class/instance methods.
// - Mixins do not define *any* instance fields. (Not sure about static


what do you think?)

This seems a little arbitrary. Why should this restriction be made especially give the implementation just below. I can think of a number of reason to want fields.

I just want to avoid complexity in the compiler (and in the language), and gut feel tells me this will needlessly complicate. But then, I only want behavioural decoration. I don't care about aggregation, whereas others do.
// - Mixin methods are added into the mixing class as if the user had typed


in

Yes
// - Mixins have *no* polymorphic aspects whatsoever. Two classes that each


//   the same mixin are nonetheless completely unrelated

Yes
// - Mixin methods may "become" polymorphic with respect to any interface(s)


the mixing class is "implement"ing
// - If the mixing class already contains a method of the same signature, that
"overrides" - prevents incorporation - of that mixin method.

Does this include methods from a base of the class? I would say that any directly defined members of the class take precedence over the mixin method but the mixin method take precedence over and base class method.

Excellent point. I agree with you, although there'd have to be a mechanism for saying that we want the base class function, something akin to "using parent_class_type::method1();" in C++
 My view point on mixins is in line with Fred's post.  ( See my reply
 to him. )  The major difference is that I think the mixin declaration
 needs to go into the class body not the header.  The reason for this
 is that I think mixins should be able to be able to be parameterized
 by items from the declaration scope.

Can you give a motivating example?
Apr 30 2004
next sibling parent reply "Ben Hinkle" <bhinkle4 juno.com> writes:
 My view point on mixins is in line with Fred's post.  ( See my reply
 to him. )  The major difference is that I think the mixin declaration
 needs to go into the class body not the header.  The reason for this
 is that I think mixins should be able to be able to be parameterized
 by items from the declaration scope.

Can you give a motivating example?

I also agree it should go in the body. To quote your description of mixin: "Mixin methods are added into the mixing class as if the user had typed them in" and methods are typed into the body. Also since mixins have nothing to do with inheritance putting them in the same area as the superclass and interfaces is misleading. I wonder if either the "import" or "alias" keywords can be used in this context instead of making up a new keyword. In some sense mixin (as I understand it) is just snarfing the definitions of some methods from another class so it feels very close to the semantics of "import". It seems a pity to introduce a new keyword for this. Actually maybe "snarf" isn't so bad... -Ben
Apr 30 2004
parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Ben Hinkle" <bhinkle4 juno.com> wrote in message
news:c6uj3o$sjm$1 digitaldaemon.com...
 My view point on mixins is in line with Fred's post.  ( See my reply
 to him. )  The major difference is that I think the mixin declaration
 needs to go into the class body not the header.  The reason for this
 is that I think mixins should be able to be able to be parameterized
 by items from the declaration scope.

Can you give a motivating example?

I also agree it should go in the body. To quote your description of mixin: "Mixin methods are added into the mixing class as if the user had typed them in" and methods are typed into the body. Also since mixins have nothing to do with inheritance putting them in the same area as the superclass and interfaces is misleading.

But mixins, according to my definition, have nothing to do with member data whatsoever, so I would find it misleading to have them declared internal to the class. In the absence of any kind of declarative class decorators (which may well be a better alternative) I find the base list more natural even though, as you say, mixins are not involved with inheritance as we know if. (Of course, one might counter that there's nothing written in stone that the base list syntax has to mean base classes in D. You're just hung up on C++/Java syntax.) In any case, I think it's more instrumentable, and I'd hazard a guess that it's more compilable, so I stand by my proposal. {FYI: I don't like, and don't support, the use of mixins for object aggregation, so any arguments based around that are moot wrt my proposal.]
Apr 30 2004
prev sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Matthew wrote:
// - Mixins define class/instance methods.
// - Mixins do not define *any* instance fields. (Not sure about static


fields -
what do you think?)

This seems a little arbitrary. Why should this restriction be made especially give the implementation just below. I can think of a number of reason to want fields.

I just want to avoid complexity in the compiler (and in the language), and gut feel tells me this will needlessly complicate. But then, I only want behavioural decoration. I don't care about aggregation, whereas others do.

It seems like we could expand the capabilities of mixins later if necessary...but it would nearly impossible to simplify them once code was out there using the feature. I agree, keep it simple for now, and we can expand it (if needed) in 2.0.
May 04 2004
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Please clarify my understanding here.  It sounds like mixins, as you are 
describing them, are (more or less) a generalization of templates.  If I 
understand correctly, though, they allow a few more features.  But for 
the moment, bear with me.

Could I say that the Ranges mixin could also be (hackishly) implemented 
like this:


class Range(C) : C
{
    ...various fields here...
}


And then the class which mixes it would be defined like this:


template ListBase(T,B)
{
   public class List
         : B                      // base class
         , mixes Ranges    // Note: do not need to specify mixing class,
     {
     }
}

// Can you use the template shortcut syntax for a typedef?
// If so, a typedef would be better hre.
template class List(T, B = EmptyBase) : Range(ListBase(T,B)) {};


Obviously, this is a more hackish solution, plus it has more class 
overhead.  Also, in this scenario, Range cannot provide implementations 
for members of interfaces that List might want to export.  But 
otherwise, does it accomplish nearly the same purpose?

If so, then I heartily agree with your proposal and will be very excited 
to get to use it!

Russ

Matthew wrote:
 Wow, I hadn't realised that this had got so serious!
 
 I've been chatting with Walter about a mixins syntax to serve the needs of DTL,
 but had (carelessly / selfishly / stupidly / ...) not put it up on the group,
as
 I didn't have time for a debate (which I still don't).
 
 Roughly, here's my proposal, which, at first glance, appears to be quite a
 different kettle of fish to what you're talking about:
 
 // - Mixins define class/instance methods.
 // - Mixins do not define *any* instance fields. (Not sure about static fields
-
 what do you think?)
 // - Mixin methods are added into the mixing class as if the user had typed
them
 in
 // - Mixins have *no* polymorphic aspects whatsoever. Two classes that each mix
 //   the same mixin are nonetheless completely unrelated
 // - Mixin methods may "become" polymorphic with respect to any interface(s)
that
 the mixing class is "implement"ing
 // - If the mixing class already contains a method of the same signature, that
 "overrides" - prevents incorporation - of that mixin method.
 
 Syntax:
 
 mixin Ranges(C) // C is the mixing class.
 {
 private:
     typedef C.value_type    value_type; // A convenience for the mixin
 implementation, and also a constraint on C
     typedef C.index_type    index_type; // A convenience for the mixin
 implementation, and also a constraint on C
 
 public:
     boolean contains(value_type comperand)
     {
         foreach(value_type v; cast(C)(this)) // How to get to the real,
gestalt,
 entity. foreach acts as a constraint on C
         {
             if(v == comperand)
             {
                 return cast(boolean)(true);
             }
         }
 
         return cast(boolean)(false);
     }
 
     . . .
 }
 
 And is used as follows (as in the DTL classes, which require only that the
mixing
 class has value_type and index_type member types, and be freachable):
 
 template List(T, B = EmptyBase)
 {
     public class List
         : B                      // base class
         , mixes Ranges    // Note: do not need to specify mixing class, since
it
 cannot be ambiguous.
     {
     }
 }
 
 Note that a mixin could also be a template, but needn't be. In a sense, it's
 already a template, as it's parameterised by one (and only one) type, its
mixing
 class.
 
 Clearly, there are some differences between your proposal and mine:
 
 minor:
 
 - I don't like the syntax you propose (i.e. the #,  ), but this is a pretty
minor
 issue, and will be whatever Walter deems most unambiguous and easy to parse
 
 major:
 
 - you allow for mixins to provide fields
 - you allow mixins to introduce a different polymorphic nature to their mixing
 class
 - you allow mixins to have constructors, which I do not
 
 I disagree with all of these, since it seems that your mixin design is almost a
 halfway house between SI and MI and, although I understand the motivation, I
 think we'll be in murky territory.
 
 Of course, my perspective may well be covered by my needs. ;)
 
 Matthew
 
 
 
 "fred" <info fleet-manage.com> wrote in message
 news:c6s9ck$7go$1 digitaldaemon.com...
 I would like to proposed the following specification for Mixins be included as
 part of Version 1.0
 D Programming Language specification. All comments are welcomed.
 
 MIXINS SPECIFICATION      Version 0.1
 
 Introduction
 What are mixins ?
 A mixin is a class-like entity whose methods/fields are mixed-in to the mixing
 class just
 as if the author of that class had written them manually.
 As Matthew so neatly put it (see
 D/28348 )
 
 Why do we need them ?
 The rational for Mixins is quite compelling...
 One of the greatest shortcomings of the C++ language from a Object Oriented
 perspective,
 is that there is no language support for Aggregated Objects. As such,
Aggregation
 has to be
 performed programatically, often (incorrectly) using the inheritance mechanism
as
 a coding
 shortcut. By including language support we provide a direct correlation between
 OOD using
 modeling techniques like UML, and OOP.
 
 Background
 Please read the following;
 D/28455
 D/28511
 D/28553
 
 Lexical
 I propose that we use one of the two remaining (common) symbols, i.e. # and  
as
 well as
 the keyword mixin. For this document we'll use # as the mixin symbol
 
 Syntax
 There are a number of syntax alternatives that could be incorporated.
 
 Alternative A:
 class <identifier> [: <inherited-class>]
                    [# <aggregated-class> <local-identifier>]*
 
 For example;
 class Lamp : Light
            # Body      cBody
            # Switch    cSwitch
            # Globe     cGlobe
            # PowerCord cPowerCord
 {
     this() {
         super();
         cBody();                     // Body construction
         cGlobe();                    // Globe construction
         cPowerCord();                // PowerCord construction
         cSwitch(cGlobe,cPowerCord);  // Switch construction
     }
 };
 
 Alternative B:
 class <identifier> [: <inherited-class>]
                    [# <aggregated-class> <local-identifier>
                    [, <aggregated-class> <local-identifier>]*]
 
 For example;
 
 class Lamp : Light
            # Body      cBody
            , Switch    cSwitch
            , Globe     cGlobe
            , PowerCord cPowerCord
 {
     this() {
         super();
         cBody();                     // Body construction
         cGlobe();                    // Globe construction
         cPowerCord();                // PowerCord construction
         cSwitch(cGlobe,cPowerCord);  // Switch construction
     }
 };
 
 Semantics
 The rules for Mixin variables should be the same as class member declarations,
 except
 Mixins allow the interfaces of the aggregated class to be included as part of
the
 mixing class.
 This fact means that it is possible to have multiple versions of the same
member
 name
 within a mixing class.
 
 I propose a simple precedence rule, where the member defined in the class
 overrides those
 defined in the aggregated class, and those in the aggregated classes are
assigned
 according
 to the order they are declared. If this was to take place, a compiler warning
 message stating
 "that member X of aggregated class A is taking precedence over that in
aggregated
 class B"
 should be displayed in the error log.
 
 Note: there are probably other things that will need to be considered here !
 
 Conclusion
 Mixins permit externally declare classes to be used as part of a class, and in
so
 doing provides
 a real alternative to the Multiple Inheritance option provided for in the C++
 language. As such, this
 relatively insignificant addition to the language should greatly enhance the
 overall flexibility of the
 D Programming Language.
 
 Comments !
 
 

May 04 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
 Please clarify my understanding here.  It sounds like mixins, as you are
 describing them, are (more or less) a generalization of templates.

I'm not sure I'd put it like that, but I would certainly agree that they have things in common with templates.
  If I
 understand correctly, though, they allow a few more features.  But for
 the moment, bear with me.

Will do ..
 Could I say that the Ranges mixin could also be (hackishly) implemented
 like this:

 class Range(C) : C
 {
     ...various fields here...
 }


 And then the class which mixes it would be defined like this:


 template ListBase(T,B)
 {
    public class List
          : B                      // base class
          , mixes Ranges    // Note: do not need to specify mixing class,
      {
      }
 }

Yes
 // Can you use the template shortcut syntax for a typedef?
 // If so, a typedef would be better hre.
 template class List(T, B = EmptyBase) : Range(ListBase(T,B)) {};


 Obviously, this is a more hackish solution, plus it has more class
 overhead.  Also, in this scenario, Range cannot provide implementations
 for members of interfaces that List might want to export.  But
 otherwise, does it accomplish nearly the same purpose?

Sorry, dude, I just don't get it. Can you explain this example more thoroughly?
 If so, then I heartily agree with your proposal and will be very excited
 to get to use it!

Ah, a man of great wisdom. ;)
 Russ

 Matthew wrote:
 Wow, I hadn't realised that this had got so serious!

 I've been chatting with Walter about a mixins syntax to serve the needs of


 but had (carelessly / selfishly / stupidly / ...) not put it up on the group,


 I didn't have time for a debate (which I still don't).

 Roughly, here's my proposal, which, at first glance, appears to be quite a
 different kettle of fish to what you're talking about:

 // - Mixins define class/instance methods.
 // - Mixins do not define *any* instance fields. (Not sure about static


 what do you think?)
 // - Mixin methods are added into the mixing class as if the user had typed


 in
 // - Mixins have *no* polymorphic aspects whatsoever. Two classes that each


 //   the same mixin are nonetheless completely unrelated
 // - Mixin methods may "become" polymorphic with respect to any interface(s)


 the mixing class is "implement"ing
 // - If the mixing class already contains a method of the same signature,


 "overrides" - prevents incorporation - of that mixin method.

 Syntax:

 mixin Ranges(C) // C is the mixing class.
 {
 private:
     typedef C.value_type    value_type; // A convenience for the mixin
 implementation, and also a constraint on C
     typedef C.index_type    index_type; // A convenience for the mixin
 implementation, and also a constraint on C

 public:
     boolean contains(value_type comperand)
     {
         foreach(value_type v; cast(C)(this)) // How to get to the real,


 entity. foreach acts as a constraint on C
         {
             if(v == comperand)
             {
                 return cast(boolean)(true);
             }
         }

         return cast(boolean)(false);
     }

     . . .
 }

 And is used as follows (as in the DTL classes, which require only that the


 class has value_type and index_type member types, and be freachable):

 template List(T, B = EmptyBase)
 {
     public class List
         : B                      // base class
         , mixes Ranges    // Note: do not need to specify mixing class, since


 cannot be ambiguous.
     {
     }
 }

 Note that a mixin could also be a template, but needn't be. In a sense, it's
 already a template, as it's parameterised by one (and only one) type, its


 class.

 Clearly, there are some differences between your proposal and mine:

 minor:

 - I don't like the syntax you propose (i.e. the #,  ), but this is a pretty


 issue, and will be whatever Walter deems most unambiguous and easy to parse

 major:

 - you allow for mixins to provide fields
 - you allow mixins to introduce a different polymorphic nature to their


 class
 - you allow mixins to have constructors, which I do not

 I disagree with all of these, since it seems that your mixin design is almost


 halfway house between SI and MI and, although I understand the motivation, I
 think we'll be in murky territory.

 Of course, my perspective may well be covered by my needs. ;)

 Matthew



 "fred" <info fleet-manage.com> wrote in message
 news:c6s9ck$7go$1 digitaldaemon.com...
 I would like to proposed the following specification for Mixins be included


 part of Version 1.0
 D Programming Language specification. All comments are welcomed.

 MIXINS SPECIFICATION      Version 0.1

 Introduction
 What are mixins ?
 A mixin is a class-like entity whose methods/fields are mixed-in to the


 class just
 as if the author of that class had written them manually.
 As Matthew so neatly put it (see
 D/28348 )

 Why do we need them ?
 The rational for Mixins is quite compelling...
 One of the greatest shortcomings of the C++ language from a Object Oriented
 perspective,
 is that there is no language support for Aggregated Objects. As such,


 has to be
 performed programatically, often (incorrectly) using the inheritance


 a coding
 shortcut. By including language support we provide a direct correlation


 OOD using
 modeling techniques like UML, and OOP.

 Background
 Please read the following;
 D/28455
 D/28511
 D/28553

 Lexical
 I propose that we use one of the two remaining (common) symbols, i.e. # and  


 well as
 the keyword mixin. For this document we'll use # as the mixin symbol

 Syntax
 There are a number of syntax alternatives that could be incorporated.

 Alternative A:
 class <identifier> [: <inherited-class>]
                    [# <aggregated-class> <local-identifier>]*

 For example;
 class Lamp : Light
            # Body      cBody
            # Switch    cSwitch
            # Globe     cGlobe
            # PowerCord cPowerCord
 {
     this() {
         super();
         cBody();                     // Body construction
         cGlobe();                    // Globe construction
         cPowerCord();                // PowerCord construction
         cSwitch(cGlobe,cPowerCord);  // Switch construction
     }
 };

 Alternative B:
 class <identifier> [: <inherited-class>]
                    [# <aggregated-class> <local-identifier>
                    [, <aggregated-class> <local-identifier>]*]

 For example;

 class Lamp : Light
            # Body      cBody
            , Switch    cSwitch
            , Globe     cGlobe
            , PowerCord cPowerCord
 {
     this() {
         super();
         cBody();                     // Body construction
         cGlobe();                    // Globe construction
         cPowerCord();                // PowerCord construction
         cSwitch(cGlobe,cPowerCord);  // Switch construction
     }
 };

 Semantics
 The rules for Mixin variables should be the same as class member


 except
 Mixins allow the interfaces of the aggregated class to be included as part of


 mixing class.
 This fact means that it is possible to have multiple versions of the same


 name
 within a mixing class.

 I propose a simple precedence rule, where the member defined in the class
 overrides those
 defined in the aggregated class, and those in the aggregated classes are


 according
 to the order they are declared. If this was to take place, a compiler warning
 message stating
 "that member X of aggregated class A is taking precedence over that in


 class B"
 should be displayed in the error log.

 Note: there are probably other things that will need to be considered here !

 Conclusion
 Mixins permit externally declare classes to be used as part of a class, and


 doing provides
 a real alternative to the Multiple Inheritance option provided for in the C++
 language. As such, this
 relatively insignificant addition to the language should greatly enhance the
 overall flexibility of the
 D Programming Language.

 Comments !


May 04 2004
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Matthew wrote:
Could I say that the Ranges mixin could also be (hackishly) implemented
like this:

class Range(C) : C
{
    ...various fields here...
}


And then the class which mixes it would be defined like this:


template ListBase(T,B)
{
   public class List
         : B                      // base class
         , mixes Ranges    // Note: do not need to specify mixing class,
     {
     }
}

Yes
// Can you use the template shortcut syntax for a typedef?
// If so, a typedef would be better hre.
template class List(T, B = EmptyBase) : Range(ListBase(T,B)) {};


Obviously, this is a more hackish solution, plus it has more class
overhead.  Also, in this scenario, Range cannot provide implementations
for members of interfaces that List might want to export.  But
otherwise, does it accomplish nearly the same purpose?

Sorry, dude, I just don't get it. Can you explain this example more thoroughly?

What I was trying to illustrate is that you can define a template which adds member functions to an existing class, which is sort of like a mixin. However, I like your mixin syntax because 1) Looks cleaner 2) You only declare 1 class, rather than 3 (List rather than List->Range(ListBase)->ListBase) 3) In your mixin definition, you can have List implement an interface which includes some functions from List and some from Range. This is not possible with the template solution.
May 04 2004
next sibling parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:c79osk$2ggk$1 digitaldaemon.com...
 Matthew wrote:
Could I say that the Ranges mixin could also be (hackishly) implemented
like this:

class Range(C) : C
{
    ...various fields here...
}


And then the class which mixes it would be defined like this:


template ListBase(T,B)
{
   public class List
         : B                      // base class
         , mixes Ranges    // Note: do not need to specify mixing class,
     {
     }
}

Yes
// Can you use the template shortcut syntax for a typedef?
// If so, a typedef would be better hre.
template class List(T, B = EmptyBase) : Range(ListBase(T,B)) {};


Obviously, this is a more hackish solution, plus it has more class
overhead.  Also, in this scenario, Range cannot provide implementations
for members of interfaces that List might want to export.  But
otherwise, does it accomplish nearly the same purpose?

Sorry, dude, I just don't get it. Can you explain this example more


 What I was trying to illustrate is that you can define a template which
 adds member functions to an existing class, which is sort of like a
 mixin.  However, I like your mixin syntax because
 1) Looks cleaner
 2) You only declare 1 class, rather than 3 (List rather than
 List->Range(ListBase)->ListBase)
 3) In your mixin definition, you can have List implement an interface
 which includes some functions from List and some from Range.  This is
 not possible with the template solution.

Yes, I thought about several different ideas before this one just grabbed me by the you-know-whats. I'm having difficulty persuading Walter that it's the one true way, however, so it may not see the real world. We'll just have to see ...
May 04 2004
prev sibling parent "Achilleas Margaritis" <axilmar in.gr> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:c79osk$2ggk$1 digitaldaemon.com...
 Matthew wrote:
Could I say that the Ranges mixin could also be (hackishly) implemented
like this:

class Range(C) : C
{
    ...various fields here...
}


And then the class which mixes it would be defined like this:


template ListBase(T,B)
{
   public class List
         : B                      // base class
         , mixes Ranges    // Note: do not need to specify mixing class,
     {
     }
}

Yes
// Can you use the template shortcut syntax for a typedef?
// If so, a typedef would be better hre.
template class List(T, B = EmptyBase) : Range(ListBase(T,B)) {};


Obviously, this is a more hackish solution, plus it has more class
overhead.  Also, in this scenario, Range cannot provide implementations
for members of interfaces that List might want to export.  But
otherwise, does it accomplish nearly the same purpose?

Sorry, dude, I just don't get it. Can you explain this example more


 What I was trying to illustrate is that you can define a template which
 adds member functions to an existing class, which is sort of like a
 mixin.  However, I like your mixin syntax because
 1) Looks cleaner
 2) You only declare 1 class, rather than 3 (List rather than
 List->Range(ListBase)->ListBase)
 3) In your mixin definition, you can have List implement an interface
 which includes some functions from List and some from Range.  This is
 not possible with the template solution.

Mixins can be a different construct, like a struct/class/interface.
May 05 2004