May 18, 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
[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
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:
> 
>> 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?

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.



> 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
"Ben Hinkle" <bhinkle4@juno.com> wrote in message news:c8d08c$krr$1@digitaldaemon.com...
> [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.

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 19, 2004
In article <c8c76s$2cvn$1@digitaldaemon.com>, Andy Friesen says...
>
>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

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.

Kevin


1 2
Next ›   Last »