digitalmars.D - Mixins & init code, others
- Mike Swieton (19/19) May 17 2004 It would be extremely useful to have mixins have constructors for some
- fred (27/41) May 17 2004 How about something like this ??
- Walter (8/27) May 17 2004 Actually, you can mix in constructors. Just put a 'this' method in the
- Andy Friesen (21/23) May 17 2004 I think he means something like this: (which does not work)
- Roel Mathys (22/54) May 17 2004 this does work,
- Roel Mathys (22/90) May 17 2004 something like this, please don't flame for abusing some feature :-)
- Roel Mathys (23/124) May 17 2004 apparantly, the mixin's must be directly in the scope of class, then you...
- Vathix (32/55) May 17 2004 How about constructors without parameter lists are implicitly called in
- Russ Lewis (18/50) May 18 2004 I guess the solution might be...and I agree that it's suboptimal:
- Kevin Bealer (9/32) May 18 2004 If something is complex enough to need constructors then perhaps it is b...
- Michael Coupland (34/36) May 17 2004 That still doesn't work very well if your goal is to guarantee that your...
- Walter (10/45) May 18 2004 problem:
- Ben Hinkle (15/16) May 18 2004 [snip]
- Walter (11/27) May 18 2004 the
- Norbert Nemec (23/23) May 18 2004 What about this:
- Norbert Nemec (9/31) May 18 2004 I think, there is a simple solution for this:
- Mike Swieton (20/29) May 18 2004 It is true that automatically assembling a constructor is probably a bad...
- Norbert Nemec (35/60) May 18 2004 True, sorry, editing that sentence a few times, it got screwed up
It would be extremely useful to have mixins have constructors for some initialization, i.e. a constructor. Has anyone figured out how to do this? I've come up with some cheap hack solutions, but nothing that really works well. I'd settle for "mixin ctor code is lexically composed with each ctor of the mixed class". But a little ability for initializing the data would be extremely handy. A second, and most likely more important item: mixins need to support invariants. The above is much less important if I can use an invariant to inforce that a manually called init method has been called. This also should not be complex: a lexical composition would work perfectly fine (although scoping rules would have to be determined). Has anyone thought about this? The lack of ctors and invariants I think somewhat limits the utility of mixing classes, because one cannot provide good initialization of data in any way. Mike Swieton __ Computer Science is the only discipline in which we view adding a new wing to a building as being maintenance. - Jim Horning
May 17 2004
"Mike Swieton" <mike swieton.net> wrote in message news:pan.2004.05.18.02.44.03.517824 swieton.net...It would be extremely useful to have mixins have constructors for some initialization, i.e. a constructor. Has anyone figured out how to do this? I've come up with some cheap hack solutions, but nothing that really works well. I'd settle for "mixin ctor code is lexically composed with each ctor of the mixed class". But a little ability for initializing the data would be extremely handy.How about something like this ?? class Part { this(int param) { v = param; } int Value() { return v; } private: int v; } template Construct!( T, alias param ) { T part = new T(param); } class Some { this(int param) { x = param; } private: int x; mixin Construct!( Part, x*2 ) part; } int main() { Some some(5); return some.part.Value(); // will return 10 }A second, and most likely more important item: mixins need to support invariants. The above is much less important if I can use an invariant to inforce that a manually called init method has been called. This also should not be complex: a lexical composition would work perfectly fine (although scoping rules would have to be determined). Has anyone thought about this? The lack of ctors and invariants I think somewhat limits the utility of mixing classes, because one cannot provide good initialization of data in any way.Have you got any code that could explain this further ? cheers fred
May 17 2004
Actually, you can mix in constructors. Just put a 'this' method in the template. "Mike Swieton" <mike swieton.net> wrote in message news:pan.2004.05.18.02.44.03.517824 swieton.net...It would be extremely useful to have mixins have constructors for some initialization, i.e. a constructor. Has anyone figured out how to do this? I've come up with some cheap hack solutions, but nothing that really works well. I'd settle for "mixin ctor code is lexically composed with each ctorofthe mixed class". But a little ability for initializing the data would be extremely handy. A second, and most likely more important item: mixins need to support invariants. The above is much less important if I can use an invariant to inforce that a manually called init method has been called. This alsoshouldnot be complex: a lexical composition would work perfectly fine (although scoping rules would have to be determined). Has anyone thought about this? The lack of ctors and invariants I think somewhat limits the utility of mixing classes, because one cannot providegoodinitialization of data in any way. Mike Swieton __ Computer Science is the only discipline in which we view adding a new wingtoa building as being maintenance. - Jim Horning
May 17 2004
Walter wrote:Actually, you can mix in constructors. Just put a 'this' method in the template.I think he means something like this: (which does not work) template Mix1() { this() { printf("mix1\n"); } } template Mix2() { this() { printf("Mix2!\n"); } } class Bar { mixin Mix1; mixin Mix2; } int main() { Bar bar = new Bar(); return 0; } I think this is part of the can of worms that Matthew was talking about* when he suggested not allowing mixins to add attributes. Not only do mixins require constructors, they need to have invariants as well. * here: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/133 -- andy
May 17 2004
Andy Friesen wrote:Walter wrote:this does work, template Mix1() { this() { printf("mix1\n"); } } template Mix2() { this(int x) { printf("Mix2!\n"); } } class Bar { mixin Mix1; mixin Mix2; } int main() { Bar bar = new Bar(); return 0; } mayb it would be better if a this defined this way somehow magically attaches itself to the original ctor, bye, roel ps: the only place I like magic is in a good bookActually, you can mix in constructors. Just put a 'this' method in the template.I think he means something like this: (which does not work) template Mix1() { this() { printf("mix1\n"); } } template Mix2() { this() { printf("Mix2!\n"); } } class Bar { mixin Mix1; mixin Mix2; } int main() { Bar bar = new Bar(); return 0; } I think this is part of the can of worms that Matthew was talking about* when he suggested not allowing mixins to add attributes. Not only do mixins require constructors, they need to have invariants as well. * here: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/133 -- andy
May 17 2004
Roel Mathys wrote:Andy Friesen wrote:something like this, please don't flame for abusing some feature :-) template Mix1() { void Mix1() { printf("mix1\n"); } } template Mix2() { void Mix2() { printf("Mix2!\n"); } } class Bar { int myx; this() in { mixin Mix1; Mix1(); } out { mixin Mix2; Mix2(); } body { myx = 15; } } int main() { Bar bar = new Bar(); return 0; } bye, roelWalter wrote:this does work, template Mix1() { this() { printf("mix1\n"); } } template Mix2() { this(int x) { printf("Mix2!\n"); } } class Bar { mixin Mix1; mixin Mix2; } int main() { Bar bar = new Bar(); return 0; } mayb it would be better if a this defined this way somehow magically attaches itself to the original ctor, bye, roel ps: the only place I like magic is in a good bookActually, you can mix in constructors. Just put a 'this' method in the template.I think he means something like this: (which does not work) template Mix1() { this() { printf("mix1\n"); } } template Mix2() { this() { printf("Mix2!\n"); } } class Bar { mixin Mix1; mixin Mix2; } int main() { Bar bar = new Bar(); return 0; } I think this is part of the can of worms that Matthew was talking about* when he suggested not allowing mixins to add attributes. Not only do mixins require constructors, they need to have invariants as well. * here: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/133 -- andy
May 17 2004
Roel Mathys wrote:Roel Mathys wrote:apparantly, the mixin's must be directly in the scope of class, then you can access members of the class bye, roel ---------------------------------------------------- template Mix1() { void Mix1() { myx = 1; }} template Mix2() { void Mix2() { myx = 2; }} class Bar { int myx; mixin Mix1; mixin Mix2; this() in { Mix1(); } out { Mix2(); } body { myx = 15; } } int main() { Bar bar = new Bar(); printf("myx = %d\n",bar.myx); return 0; }Andy Friesen wrote:something like this, please don't flame for abusing some feature :-) template Mix1() { void Mix1() { printf("mix1\n"); } } template Mix2() { void Mix2() { printf("Mix2!\n"); } } class Bar { int myx; this() in { mixin Mix1; Mix1(); } out { mixin Mix2; Mix2(); } body { myx = 15; } } int main() { Bar bar = new Bar(); return 0; } bye, roelWalter wrote:this does work, template Mix1() { this() { printf("mix1\n"); } } template Mix2() { this(int x) { printf("Mix2!\n"); } } class Bar { mixin Mix1; mixin Mix2; } int main() { Bar bar = new Bar(); return 0; } mayb it would be better if a this defined this way somehow magically attaches itself to the original ctor, bye, roel ps: the only place I like magic is in a good bookActually, you can mix in constructors. Just put a 'this' method in the template.I think he means something like this: (which does not work) template Mix1() { this() { printf("mix1\n"); } } template Mix2() { this() { printf("Mix2!\n"); } } class Bar { mixin Mix1; mixin Mix2; } int main() { Bar bar = new Bar(); return 0; } I think this is part of the can of worms that Matthew was talking about* when he suggested not allowing mixins to add attributes. Not only do mixins require constructors, they need to have invariants as well. * here: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/133 -- andy
May 17 2004
"Andy Friesen" <andy ikagames.com> wrote in message news:c8c76s$2cvn$1 digitaldaemon.com...Walter wrote:How about constructors without parameter lists are implicitly called in order (as well as destructors), and if they take parameters, you have to have your constructor call them. Like this: template Mix1() { this() { printf("mix1\n"); } } template Mix2(int stuff) { // Note the parameter list. this(int stuff) { printf("Mix2!\n"); } ~this() { /* stuff */ } } class Bar { mixin Mix1; mixin Mix2; this() { // Mix1.this() // Implied. Mix2.this(4); // Required. } // ~this() { Mix2.~this(); } // Implied, or implicitly added to the end of an existing destructor. } If you have a long complicated mixin like Foo!(Stuff!(a, b, c!(d, e), f!(etc))) then just alias it. aliasname.this(...). Or if it has a mixin identifier then you can just use that name. Constructors aren't like normal functions, you can't mix them in like a regular function because all initializations need to occur.Actually, you can mix in constructors. Just put a 'this' method in the template.I think he means something like this: (which does not work) template Mix1() { this() { printf("mix1\n"); } } template Mix2() { this() { printf("Mix2!\n"); } } class Bar { mixin Mix1; mixin Mix2; } int main() { Bar bar = new Bar(); return 0; } I think this is part of the can of worms that Matthew was talking about* when he suggested not allowing mixins to add attributes. Not only do mixins require constructors, they need to have invariants as well. * here: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/133 -- andy
May 17 2004
I guess the solution might be...and I agree that it's suboptimal: template Mix1() { void init() { ... } } template Mix2() { void init() { ... } } class Bar { mixin Mix1 M1; mixin Mix2 M2; this() { M1.init(); M2.init(); } } Of course, it would be nice to not have to call this by hand, but this way you can call init() with arguments if you wanted. Andy Friesen wrote:Walter wrote:Actually, you can mix in constructors. Just put a 'this' method in the template.I think he means something like this: (which does not work) template Mix1() { this() { printf("mix1\n"); } } template Mix2() { this() { printf("Mix2!\n"); } } class Bar { mixin Mix1; mixin Mix2; } int main() { Bar bar = new Bar(); return 0; } I think this is part of the can of worms that Matthew was talking about* when he suggested not allowing mixins to add attributes. Not only do mixins require constructors, they need to have invariants as well. * here: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/133 -- andy
May 18 2004
In article <c8c76s$2cvn$1 digitaldaemon.com>, Andy Friesen says...Walter wrote:If something is complex enough to need constructors then perhaps it is better not to mix it, but to just include it as a regular member field. If it has a constructor, does that imply that it has a "this" pointer? If so, it could be assigned to another field somewhere; the GC has to keep it around, so it would be better as a seperate object, maybe. Not to disagree; but the actual purposes of the mixing are not clear to me. It seems like a useful feature, but when to use and when not? I dunno yet. KevinActually, you can mix in constructors. Just put a 'this' method in the template.I think he means something like this: (which does not work) template Mix1() { this() { printf("mix1\n"); } } template Mix2() { this() { printf("Mix2!\n"); } } class Bar { mixin Mix1; mixin Mix2; } int main() { Bar bar = new Bar(); return 0; } I think this is part of the can of worms that Matthew was talking about* when he suggested not allowing mixins to add attributes. Not only do mixins require constructors, they need to have invariants as well. * here: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/133 -- andy
May 18 2004
Walter wrote:Actually, you can mix in constructors. Just put a 'this' method in the template.That still doesn't work very well if your goal is to guarantee that your constructor is executed. (A handy thing to have happen...) I was just playing around with mixins, and the following code demonstrates the problem: ---------- template MixVar() { this() { mixed_var = 1; } int mixed_var; } class MixTarg { this( ) { targ_var = 2; } int targ_var; mixin MixVar; void print() { printf( "(%d, %d)", targ_var, mixed_var ); } } int main( char[][] args ) { MixTarg test = new MixTarg(); test.print(); return 0; } ---------- The output is: (2, 0) Rather than the (expected? hoped-for?): (2, 1) So I guess the question is, is there a way to have the mixin's constructor called /in addition to/ whatever constructor is called for the base class. (The current way you can merely supply new constructors, and (as this example shows) they won't override any existing constructors of identical signature. Michael
May 17 2004
"Michael Coupland" <mcoupland hmc.edu> wrote in message news:c8c8dp$2f2v$1 digitaldaemon.com...Walter wrote:problem:Actually, you can mix in constructors. Just put a 'this' method in the template.That still doesn't work very well if your goal is to guarantee that your constructor is executed. (A handy thing to have happen...) I was just playing around with mixins, and the following code demonstrates the---------- template MixVar() { this() { mixed_var = 1; } int mixed_var; } class MixTarg { this( ) { targ_var = 2; } int targ_var; mixin MixVar; void print() { printf( "(%d, %d)", targ_var, mixed_var ); } } int main( char[][] args ) { MixTarg test = new MixTarg(); test.print(); return 0; } ---------- The output is: (2, 0) Rather than the (expected? hoped-for?): (2, 1) So I guess the question is, is there a way to have the mixin's constructor called /in addition to/ whatever constructor is called for the base class. (The current way you can merely supply new constructors, and (as this example shows) they won't override any existing constructors of identical signature.What is happening here is any declarations in the current scope *override* declarations in a mixin scope when looking at it from outside the mixin. The idea is to have a generic version in the mixin, and perhaps a customized version to override it. Mixins aren't classes or structs. They're merely a list of declarations that acquire meaning *after* they are mixed in, and they take on meaning based on where they are mixed in, i.e. becoming struct members, class members, local variables, etc.
May 18 2004
[snip]Mixins aren't classes or structs.[snip] This is a key point. The doc should have a table or paragraph explaining the different behaviors. Something like features class struct template interface constructor yes no no no member fcns yes yes yes decls-only data members yes yes yes no inheritance single no no multiple instantiable yes yes no no defines a type yes yes no yes mixin no no yes no cls invariants yes no no no Also it would be nice to know what techniques people use to fill in some of those pesky "no"s.
May 18 2004
"Ben Hinkle" <bhinkle4 juno.com> wrote in message news:c8d08c$krr$1 digitaldaemon.com...[snip]theMixins aren't classes or structs.[snip] This is a key point. The doc should have a table or paragraph explainingdifferent behaviors. Something like features class struct template interface constructor yes no no no member fcns yes yes yes decls-only data members yes yes yes no inheritance single no no multiple instantiable yes yes no no defines a type yes yes no yes mixin no no yes no cls invariants yes no no no Also it would be nice to know what techniques people use to fill in someofthose pesky "no"s.The table is a good idea, but it doesn't resolve this particular problem. You *can* write a constructor in a mixin, it just becomes the constructor for the enclosing class if it is mixed into a class, and an error if mixed into something else. Also, that constructor can be overridden in the mixed class. Think of mixins like embryonic 'stem cells' that differentiate into muscle, bone, nerve, etc., based on where in the body they find themselves <g>.
May 18 2004
What about this: ------------------------------- template MixVar() { int mixed_var = 1; } class MixTarg { int targ_var = 2; mixin MixVar; void print() { printf( "(%d, %d)", targ_var, mixed_var ); } } int main( char[][] args ) { MixTarg test = new MixTarg(); test.print(); return 0; } ------------------------------ Finding a way to assemble constructors from different parts will be extremely complicated. Default arguments are not as flexible as code in a constructor, but they should be sufficient in most cases.
May 18 2004
I think, there is a simple solution for this: * allowing multiple invariants in one class should not be a trivial change to the language and the compiler. * instead of thinking of constructors in mixins, you should consider using default values for class member variables. Of course, default values are not as flexible as code in a constructor, but finding a way to extend the language to assemble a constructor automatically from different routines will be awfully difficult. Mike Swieton wrote:It would be extremely useful to have mixins have constructors for some initialization, i.e. a constructor. Has anyone figured out how to do this? I've come up with some cheap hack solutions, but nothing that really works well. I'd settle for "mixin ctor code is lexically composed with each ctor of the mixed class". But a little ability for initializing the data would be extremely handy. A second, and most likely more important item: mixins need to support invariants. The above is much less important if I can use an invariant to inforce that a manually called init method has been called. This also should not be complex: a lexical composition would work perfectly fine (although scoping rules would have to be determined). Has anyone thought about this? The lack of ctors and invariants I think somewhat limits the utility of mixing classes, because one cannot provide good initialization of data in any way. Mike Swieton __ Computer Science is the only discipline in which we view adding a new wing to a building as being maintenance. - Jim Horning
May 18 2004
On Tue, 18 May 2004 15:15:16 +0200, Norbert Nemec wrote:I think, there is a simple solution for this: * allowing multiple invariants in one class should not be a trivial change to the language and the compiler.I'm not sure what you mean. I think you have your logic inverted, perhaps?* instead of thinking of constructors in mixins, you should consider using default values for class member variables. Of course, default values are not as flexible as code in a constructor, but finding a way to extend the language to assemble a constructor automatically from different routines will be awfully difficult.It is true that automatically assembling a constructor is probably a bad idea. Not well thought out on my part. The specific limitation that gets me is that I have no way of instantiating a class in a mixin as part of initialization, if I don't want to use an init() method. I dislike init() methods because they do the job of a constructor. I'd prefer a syntax like: mixin Foo(args), perhaps. I'm somewhat tempted to suggest allowing code like: class X { Object x = new Object; // forbidden now } Even though I know many reasons not to want this. However, allowing for this would solve every deficiency I see. Not perfectly (to be honest, I want something more like MI, though I understand why that's not really feasible). Mike Swieton __ Go on, get out. Last words are for fools who haven't said enough. - Karl Marx, last words
May 18 2004
Mike Swieton wrote:On Tue, 18 May 2004 15:15:16 +0200, Norbert Nemec wrote:True, sorry, editing that sentence a few times, it got screwed up completely. What I meant: * allowing multiple invariants in one class *should* be a trivial change to the language and the compiler.I think, there is a simple solution for this: * allowing multiple invariants in one class should not be a trivial change to the language and the compiler.I'm not sure what you mean. I think you have your logic inverted, perhaps?It is true that automatically assembling a constructor is probably a bad idea. Not well thought out on my part.Thinking again, maybe not. See below.The specific limitation that gets me is that I have no way of instantiating a class in a mixin as part of initialization, if I don't want to use an init() method. I dislike init() methods because they do the job of a constructor. I'd prefer a syntax like: mixin Foo(args), perhaps. I'm somewhat tempted to suggest allowing code like: class X { Object x = new Object; // forbidden now } Even though I know many reasons not to want this. However, allowing for this would solve every deficiency I see. Not perfectly (to be honest, I want something more like MI, though I understand why that's not really feasible).One alternative to that might be to allow "class initializers" in addition to constructors. Like: class X { Object x; initialize { x = new Object; } ~this() { delete x; } Object y; initialize { y = new Object; } ~this() { delete y; } this() { do_something(); } this(int x) { so_some_other_thing(); } } These initializers would than just be called in order of appearance before the code of a constructor is called. There still is you could still define different constructors with zero or more arguments, but any initialization that is independant of these arguments could be moved out of the constructor into a initializer. For destructors, the situation is simpler: They do not take any arguments, so there is no problem to allow multiple destructors in one class which are then simply concatenated in *reverse* order of appearance.
May 18 2004