|
Archives
D Programming
D
D.gnu
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger
C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows
digitalmars.empire
digitalmars.DMDScript
|
D - COMMENTS: Mixins Specification
↑ ↓ ← → "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 !
↑ ↓ ← → 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/
↑ ↓ ← → "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 !
↑ ↓ ← → 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 {...}
↑ ↓ ← → "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.
↑ ↓ ← → 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
↑ ↓ ← → "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.
↑ ↓ ← → 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
↑ ↓ ← → 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/
↑ ↓ ← → "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/
↑ ↓ ← → 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/
↑ ↓ ← → 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.
↑ ↓ ← → "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?
↑ ↓ ← → "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
↑ ↓ ← → "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.]
↑ ↓ ← → 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.
↑ ↓ ← → 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 !
↑ ↓ ← → "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 !
↑ ↓ ← → 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.
↑ ↓ ← → "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 ...
↑ ↓ ← → "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.
|
|