August 13, 2008
"superdan" wrote
> Lars Ivar Igesund Wrote:
>
>> Chris R. Miller wrote:
>>
>> > Understand, I'm NOT demanding ANYTHING.
>> >
>> > What is the current state of thought about Multiple Inheritance for
>> > classes in D?  I'd like to have that feature, since it'd make some
>> > stuff
>> > I want to do a bit easier.  Is it not there because it's not worth the
>> > effort to implement?  Because it's evil and needs to die (I don't know,
>> > some people could possibly be adamantly anti-MI)?
>>
>> This is actually the reason, not the adamantly anti-MI part, just that MI
>> is
>> evil and that is well acknowledged almost everywhere. You will find good
>> argumentation against it if you look, too.
>
> appeal to authority. appeal to ridicule. appeal to the majority. all in one sentence. wow. at least could you space out your fallacies a bit more.
>
> the man has kindly asked a sensible question. he deserves a good answer. if u can't give one just don't reply. this is just ignorance.

This kind of bullying bullshit does nothing to further communication, or help anyone in the least.  You've managed to call many of the brightest developers for D idiots, usually based on useless crap like this (which has no bearing on anything).  So shut the fuck up.

> below's an attempt at an answer.

Good answer.

> interfaces could implement functions. that does make a lot of sense. example:
>
> interface Customer
> {
>    string ssn();
>    string name();
>    string uniqueName() { return name ~ "(ssn: " ~ ssn ~ ")"; }
> }
>
> so uniqueName formats a specific way. a descendant can choose to change that or just use the default. no idea why walt chose to disallow that. walt?

What do you pass as the 'this' pointer?  When you call a function on an interface, the compiler uses the offset of an interface to the 'this' pointer to get to the object, but in this case, there is no object, so what does the compiler do to call the ssn() and name() functions while implementing this function?

If you pass the interface pointer as the 'this' pointer, then how do you override it in an Object that implements the interface?  The function in the concrete class can't be passed the interface pointer, so you can't really override it.

One possible solution is to mark uniqueName as 'final', which means it cannot be overridden.  Then you can safely pass the interface pointer to the function (casting to the interface if necessary).  This might be a handy thing when you always want to implement the same function in all concrete classes in terms of the interface functions.

-Steve


August 13, 2008
Steven Schveighoffer Wrote:

> "superdan" wrote
> > Lars Ivar Igesund Wrote:
> >
> >> Chris R. Miller wrote:
> >>
> >> > Understand, I'm NOT demanding ANYTHING.
> >> >
> >> > What is the current state of thought about Multiple Inheritance for
> >> > classes in D?  I'd like to have that feature, since it'd make some
> >> > stuff
> >> > I want to do a bit easier.  Is it not there because it's not worth the
> >> > effort to implement?  Because it's evil and needs to die (I don't know,
> >> > some people could possibly be adamantly anti-MI)?
> >>
> >> This is actually the reason, not the adamantly anti-MI part, just that MI
> >> is
> >> evil and that is well acknowledged almost everywhere. You will find good
> >> argumentation against it if you look, too.
> >
> > appeal to authority. appeal to ridicule. appeal to the majority. all in one sentence. wow. at least could you space out your fallacies a bit more.
> >
> > the man has kindly asked a sensible question. he deserves a good answer. if u can't give one just don't reply. this is just ignorance.
> 
> This kind of bullying bullshit does nothing to further communication, or help anyone in the least.  You've managed to call many of the brightest developers for D idiots, usually based on useless crap like this (which has no bearing on anything).  So shut the fuck up.

or what, u gonna kick my ass. relax. you can always block me. (but hold onto that a bit more. dee's plea is just too cool.) my post did further communication. it exposed the hackneyed "mi is evil" shit... i mean poop. (damn.) it may have helped someone. you know what i like about walter. when he doesn't know something he is open in admitting it. for that alone i'd wash his feet. i didn't call the poster any name. but that particular post was bull... i mean crap and i just said it. the fact that the post sucked bears nothing on the fact that he's good or anything. even worse, if he's good then why would he use his goodwill to get away with statements like that. they only reveal ignorance and attempt at continuing ignorance because it puts a stigma on anyone investigating mi. it's silly we need to still talk about it. now shall we just move on to something technical.

> > below's an attempt at an answer.
> 
> Good answer.
> 
> > interfaces could implement functions. that does make a lot of sense. example:
> >
> > interface Customer
> > {
> >    string ssn();
> >    string name();
> >    string uniqueName() { return name ~ "(ssn: " ~ ssn ~ ")"; }
> > }
> >
> > so uniqueName formats a specific way. a descendant can choose to change that or just use the default. no idea why walt chose to disallow that. walt?
> 
> What do you pass as the 'this' pointer?  When you call a function on an interface, the compiler uses the offset of an interface to the 'this' pointer to get to the object, but in this case, there is no object, so what does the compiler do to call the ssn() and name() functions while implementing this function?

i'm unclear about this so maybe it ain't as easy as i thought. but i'm thinking the same problem goes for the global

string uniqueName(Customer c) { return c.name ~ "(ssn: " ~ c.ssn ~ ")"; }

a pointer to this function should be put in the vtable if the object does not implement it.

> If you pass the interface pointer as the 'this' pointer, then how do you override it in an Object that implements the interface?  The function in the concrete class can't be passed the interface pointer, so you can't really override it.

that pretty much kills what i wrote above eh. but thunking will take care of it. if there's no impl in an object put a pointer to a thunk that adjusts the pointer (from obj to interface) and calls the default impl with the adjusted pointer. the latter is a direct call which makes it fast.

> One possible solution is to mark uniqueName as 'final', which means it cannot be overridden.  Then you can safely pass the interface pointer to the function (casting to the interface if necessary).  This might be a handy thing when you always want to implement the same function in all concrete classes in terms of the interface functions.

that would be cool too. i recall people suggested that here before.
August 13, 2008
superdan wrote:
> Yigal Chripun Wrote:
> 
>> superdan wrote:
>>> Yigal Chripun Wrote:
>>> 
>>>> About your first thought: can you compare your (C++ templates)
>>>> solution with D mixins? why would I choose that approach
>>>> instead of template mixins if it's only good for inheritance of
>>>>  implementation? I think (and I'm sure you'll correct me if I'm
>>>>  wrong) that mixins remove the need for that pattern entirely.
>>> how would the mixin solution look like?
>> I've attached a file with a sample solution with mixins. you can put both mixins in the most derived class or put one inside the other  (as it is now)
> 
> got it. the question was how does that compare to stacked templates. guess they've about the same power. tho i suggest u move mixin B_impl outta B_impl and into A_and_B. why force A_impl as a bundle deal for B_impl.

I put one mixin inside the other just to show a similar implementation
to the c++ approach you've shown, but I agree, both mixins should be in
A_and_B (As I mentioned in my previous post).
Also note that the interfaces are only needed if you want to subtype. in
case all you need is "implementation inheritance" (as in c++) the mixins
suffice.

About non fixed layout languages, and specifically about JavaScript:
JavaScript doesn't provide MI.
it is easy to implement of course but it is not built in the language.
the language is prototype-based and each object has _one_ prototype only
from which it is "derived". if you want MI in JavaScript (and I really
don't see a reason why one would want to do it) all you need to do is
add to the object's prototype an array of all the "parent" object
prototypes and a function to search that array.
August 13, 2008
"superdan" wrote
> Steven Schveighoffer Wrote:
>
>> "superdan" wrote
>> > Lars Ivar Igesund Wrote:
>> >
>> >> Chris R. Miller wrote:
>> >>
>> >> > Understand, I'm NOT demanding ANYTHING.
>> >> >
>> >> > What is the current state of thought about Multiple Inheritance for
>> >> > classes in D?  I'd like to have that feature, since it'd make some
>> >> > stuff
>> >> > I want to do a bit easier.  Is it not there because it's not worth
>> >> > the
>> >> > effort to implement?  Because it's evil and needs to die (I don't
>> >> > know,
>> >> > some people could possibly be adamantly anti-MI)?
>> >>
>> >> This is actually the reason, not the adamantly anti-MI part, just that
>> >> MI
>> >> is
>> >> evil and that is well acknowledged almost everywhere. You will find
>> >> good
>> >> argumentation against it if you look, too.
>> >
>> > appeal to authority. appeal to ridicule. appeal to the majority. all in one sentence. wow. at least could you space out your fallacies a bit more.
>> >
>> > the man has kindly asked a sensible question. he deserves a good
>> > answer.
>> > if u can't give one just don't reply. this is just ignorance.
>>
>> This kind of bullying bullshit does nothing to further communication, or
>> help anyone in the least.  You've managed to call many of the brightest
>> developers for D idiots, usually based on useless crap like this (which
>> has
>> no bearing on anything).  So shut the fuck up.
>
> or what, u gonna kick my ass. relax. you can always block me. (but hold onto that a bit more. dee's plea is just too cool.) my post did further communication. it exposed the hackneyed "mi is evil" shit... i mean poop. (damn.) it may have helped someone. you know what i like about walter. when he doesn't know something he is open in admitting it. for that alone i'd wash his feet. i didn't call the poster any name. but that particular post was bull... i mean crap and i just said it. the fact that the post sucked bears nothing on the fact that he's good or anything. even worse, if he's good then why would he use his goodwill to get away with statements like that. they only reveal ignorance and attempt at continuing ignorance because it puts a stigma on anyone investigating mi. it's silly we need to still talk about it. now shall we just move on to something technical.

I don't want to block you.  You have some good things to say (although colorful).  Just can it with the "what you said is stupid, so don't post here"  It makes tentative posters not want to post for fear of being ridiculed (not me BTW :) )  Some of them might have interesting things to say.  If you want to argue against someone's point, argue the point (which you did later, and I found it interesting, although my personal experience with MI (on C++) is that it sucks, and should never be used).

What Lars said basically is that many people don't like MI, and you can find proof of that (people don't like it) if you search online.  This is the reason Walter doesn't implement it, because he's in that camp.  I think that is a reasonable answer to the question given.

It's sort of like most the reasons Walter gives for everything new he comes out with: "X is fundamentally broken in C++".  Substitute fundamentally broken with evil, substitute threading, const, etc. for X.  Can't say I always disagree, but his proof is certainly lacking ;)

>> > interface Customer
>> > {
>> >    string ssn();
>> >    string name();
>> >    string uniqueName() { return name ~ "(ssn: " ~ ssn ~ ")"; }
>> > }
>> >
>> > so uniqueName formats a specific way. a descendant can choose to change that or just use the default. no idea why walt chose to disallow that. walt?
>>
>> What do you pass as the 'this' pointer?  When you call a function on an
>> interface, the compiler uses the offset of an interface to the 'this'
>> pointer to get to the object, but in this case, there is no object, so
>> what
>> does the compiler do to call the ssn() and name() functions while
>> implementing this function?
>
> i'm unclear about this so maybe it ain't as easy as i thought.
> but i'm thinking the same problem goes for the global string
> uniqueName(Customer c) { return c.name ~ "(ssn: " ~ c.ssn ~ ")"; }

Not the same as the above problem, because the vtable layout for Customer is always the same.  The name() function expects a pointer to the object, and the implementation knows everything about the object including the vtable. The problem with putting the implementation in the interface is that a member function gets a pointer to the *object* not the *interface*.  In your new example, the 'c' parameter is a pointer to the interface, so that problem doesn't exist.

> a pointer to this function should be put in the vtable if the object does not implement it.

That is fine for calling the function, but not for what to do when compiling it.

>
>> If you pass the interface pointer as the 'this' pointer, then how do you
>> override it in an Object that implements the interface?  The function in
>> the
>> concrete class can't be passed the interface pointer, so you can't really
>> override it.
>
> that pretty much kills what i wrote above eh. but thunking will take care of it. if there's no impl in an object put a pointer to a thunk that adjusts the pointer (from obj to interface) and calls the default impl with the adjusted pointer. the latter is a direct call which makes it fast.

Hm... I think this would work actually, as I think this is a runtime lookup. This sounds like a reasonable tradeoff, and having the final modifier if you want it to be quicker (I think the compiler can statically do the thunk if you know the concrete object type).  Actually, it would have to do a thunk for a derived interface, even if you put final on it, as it can't always know the offset between 2 interfaces in a particular object (or can it?).

Perhaps someone with better knowledge of the way interfaces work could tell if it would be possible?

-Steve


August 13, 2008
Chris R. Miller wrote:

What about making anonymous classes legal?


class A {}
class B {}

class AB : A { class : B {} }


Granted you couldn't cast AB as a B type but you'd at least get class B's functionality...
August 13, 2008
I hate to even think of it but on this one I am with Superdan. Don't get me wrong I think he is the worst scar this group has. I think he has a real problem with the way he treats people and I wouldn't want to be his coworker or neighbor. Most of his posts are so vile I feel like puking when I read them and I blocked him a long time ago. In this thread I saw his posts in quotes and I almost wish I didn't. But I have to say if he had minimal skills at writing he would of won this argument hands down.

I for one was firmly in the "mi is evil" camp on unclear grounds of ambiguity. Lars feel-good post only inforced that. Now my understanding has changed. (Many thanks especially to Dee Girl.)

Most disappointing is one thing. When Lars answered to Superdan in a civilized manner he had an excellent opportunity at showing his class. But he missed it by neither affirming nor denying he knew about the layout problem. That leaves us facing the uncomfortable possibility that he didn't know about it but he did not have the strength to admit it.

Steven Schveighoffer Wrote:

> "superdan" wrote
> > Lars Ivar Igesund Wrote:
> >
> >> Chris R. Miller wrote:
> >>
> >> > Understand, I'm NOT demanding ANYTHING.
> >> >
> >> > What is the current state of thought about Multiple Inheritance for
> >> > classes in D?  I'd like to have that feature, since it'd make some
> >> > stuff
> >> > I want to do a bit easier.  Is it not there because it's not worth the
> >> > effort to implement?  Because it's evil and needs to die (I don't know,
> >> > some people could possibly be adamantly anti-MI)?
> >>
> >> This is actually the reason, not the adamantly anti-MI part, just that MI
> >> is
> >> evil and that is well acknowledged almost everywhere. You will find good
> >> argumentation against it if you look, too.
> >
> > appeal to authority. appeal to ridicule. appeal to the majority. all in one sentence. wow. at least could you space out your fallacies a bit more.
> >
> > the man has kindly asked a sensible question. he deserves a good answer. if u can't give one just don't reply. this is just ignorance.
> 
> This kind of bullying bullshit does nothing to further communication, or help anyone in the least.  You've managed to call many of the brightest developers for D idiots, usually based on useless crap like this (which has no bearing on anything).  So shut the fuck up.
> 
> > below's an attempt at an answer.
> 
> Good answer.
> 
> > interfaces could implement functions. that does make a lot of sense. example:
> >
> > interface Customer
> > {
> >    string ssn();
> >    string name();
> >    string uniqueName() { return name ~ "(ssn: " ~ ssn ~ ")"; }
> > }
> >
> > so uniqueName formats a specific way. a descendant can choose to change that or just use the default. no idea why walt chose to disallow that. walt?
> 
> What do you pass as the 'this' pointer?  When you call a function on an interface, the compiler uses the offset of an interface to the 'this' pointer to get to the object, but in this case, there is no object, so what does the compiler do to call the ssn() and name() functions while implementing this function?
> 
> If you pass the interface pointer as the 'this' pointer, then how do you override it in an Object that implements the interface?  The function in the concrete class can't be passed the interface pointer, so you can't really override it.
> 
> One possible solution is to mark uniqueName as 'final', which means it cannot be overridden.  Then you can safely pass the interface pointer to the function (casting to the interface if necessary).  This might be a handy thing when you always want to implement the same function in all concrete classes in terms of the interface functions.
> 
> -Steve
> 
> 

August 13, 2008
On Wed, 13 Aug 2008 19:46:51 +0400, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> "superdan" wrote
>> Steven Schveighoffer Wrote:
>>
>>> "superdan" wrote
>>> > Lars Ivar Igesund Wrote:
>>> >
>>> >> Chris R. Miller wrote:
>>> >>
>>> >> > Understand, I'm NOT demanding ANYTHING.
>>> >> >
>>> >> > What is the current state of thought about Multiple Inheritance  
>>> for
>>> >> > classes in D?  I'd like to have that feature, since it'd make some
>>> >> > stuff
>>> >> > I want to do a bit easier.  Is it not there because it's not worth
>>> >> > the
>>> >> > effort to implement?  Because it's evil and needs to die (I don't
>>> >> > know,
>>> >> > some people could possibly be adamantly anti-MI)?
>>> >>
>>> >> This is actually the reason, not the adamantly anti-MI part, just  
>>> that
>>> >> MI
>>> >> is
>>> >> evil and that is well acknowledged almost everywhere. You will find
>>> >> good
>>> >> argumentation against it if you look, too.
>>> >
>>> > appeal to authority. appeal to ridicule. appeal to the majority. all  
>>> in
>>> > one sentence. wow. at least could you space out your fallacies a bit
>>> > more.
>>> >
>>> > the man has kindly asked a sensible question. he deserves a good
>>> > answer.
>>> > if u can't give one just don't reply. this is just ignorance.
>>>
>>> This kind of bullying bullshit does nothing to further communication, or
>>> help anyone in the least.  You've managed to call many of the brightest
>>> developers for D idiots, usually based on useless crap like this (which
>>> has
>>> no bearing on anything).  So shut the fuck up.
>>
>> or what, u gonna kick my ass. relax. you can always block me. (but hold
>> onto that a bit more. dee's plea is just too cool.) my post did further
>> communication. it exposed the hackneyed "mi is evil" shit... i mean poop.
>> (damn.) it may have helped someone. you know what i like about walter.
>> when he doesn't know something he is open in admitting it. for that alone
>> i'd wash his feet. i didn't call the poster any name. but that particular
>> post was bull... i mean crap and i just said it. the fact that the post
>> sucked bears nothing on the fact that he's good or anything. even worse,
>> if he's good then why would he use his goodwill to get away with
>> statements like that. they only reveal ignorance and attempt at continuing
>> ignorance because it puts a stigma on anyone investigating mi. it's silly
>> we need to still talk about it. now shall we just move on to something
>> technical.
>
> I don't want to block you.  You have some good things to say (although
> colorful).  Just can it with the "what you said is stupid, so don't post
> here"  It makes tentative posters not want to post for fear of being
> ridiculed (not me BTW :) )  Some of them might have interesting things to
> say.  If you want to argue against someone's point, argue the point (which
> you did later, and I found it interesting, although my personal experience
> with MI (on C++) is that it sucks, and should never be used).
>
> What Lars said basically is that many people don't like MI, and you can find
> proof of that (people don't like it) if you search online.  This is the
> reason Walter doesn't implement it, because he's in that camp.  I think that
> is a reasonable answer to the question given.
>
> It's sort of like most the reasons Walter gives for everything new he comes
> out with: "X is fundamentally broken in C++".  Substitute fundamentally
> broken with evil, substitute threading, const, etc. for X.  Can't say I
> always disagree, but his proof is certainly lacking ;)
>
>>> > interface Customer
>>> > {
>>> >    string ssn();
>>> >    string name();
>>> >    string uniqueName() { return name ~ "(ssn: " ~ ssn ~ ")"; }
>>> > }
>>> >
>>> > so uniqueName formats a specific way. a descendant can choose to  
>>> change
>>> > that or just use the default. no idea why walt chose to disallow  
>>> that.
>>> > walt?
>>>
>>> What do you pass as the 'this' pointer?  When you call a function on an
>>> interface, the compiler uses the offset of an interface to the 'this'
>>> pointer to get to the object, but in this case, there is no object, so
>>> what
>>> does the compiler do to call the ssn() and name() functions while
>>> implementing this function?
>>
>> i'm unclear about this so maybe it ain't as easy as i thought.
>> but i'm thinking the same problem goes for the global string
>> uniqueName(Customer c) { return c.name ~ "(ssn: " ~ c.ssn ~ ")"; }
>
> Not the same as the above problem, because the vtable layout for Customer is
> always the same.  The name() function expects a pointer to the object, and
> the implementation knows everything about the object including the vtable.
> The problem with putting the implementation in the interface is that a
> member function gets a pointer to the *object* not the *interface*.  In your
> new example, the 'c' parameter is a pointer to the interface, so that
> problem doesn't exist.
>
>> a pointer to this function should be put in the vtable if the object does
>> not implement it.
>
> That is fine for calling the function, but not for what to do when compiling
> it.
>
>>
>>> If you pass the interface pointer as the 'this' pointer, then how do you
>>> override it in an Object that implements the interface?  The function in
>>> the
>>> concrete class can't be passed the interface pointer, so you can't really
>>> override it.
>>
>> that pretty much kills what i wrote above eh. but thunking will take care
>> of it. if there's no impl in an object put a pointer to a thunk that
>> adjusts the pointer (from obj to interface) and calls the default impl
>> with the adjusted pointer. the latter is a direct call which makes it
>> fast.
>
> Hm... I think this would work actually, as I think this is a runtime lookup.
> This sounds like a reasonable tradeoff, and having the final modifier if you
> want it to be quicker (I think the compiler can statically do the thunk if
> you know the concrete object type).  Actually, it would have to do a thunk
> for a derived interface, even if you put final on it, as it can't always
> know the offset between 2 interfaces in a particular object (or can it?).
>
> Perhaps someone with better knowledge of the way interfaces work could tell
> if it would be possible?
>
> -Steve
>
>

I use MI often and have positive experience with it. One good pattern that I use is the Intrusive container.
Suppose you have an item that you want to store in a list. Unfortunately, putting stuff into the single- or double-linked list leads to a memory allocation (unless some pool is used). Sometimes it is desirable to put next and prev elements into the item itself, so that no memory allocation is ever needed. Besides, now you can easily say whether an item is stored in any container. This can be implemented via inheritance:

class IntrusiveContainerNode(T)
{
    alias T ValueType;
    package T next;
    package T prev;
}

class IntrusiveContainer(TNode)
{
    alias TNode.ValueType ValueType;

    void add(ValueType value);
    void remove(ValueType value);
}

class MyClass : public Node!(MyClass)
{
   // ...
}

This imposes the restriction that an item can be stored in 1 container at a time. However, you can subclass twise in order to be storable in different containers:

typedef EventOneListener IntrusiveContainerNode;
typedef EventTwoListener IntrusiveContainerNode;

class MyClass : EventOneListener!(MyClass), EventTwoListener!(MyClass)
{
    // ...
}

MyClass instance = new MyClass();
eventOneListeners.add(instance);
eventTwoListeners.add(instance);

It is currently impossible to implement this approach using mixins (due to a bug I'm yet to submit).
August 13, 2008
Dee Girl Wrote:

> Chris R. Miller Wrote:
> 
> > superdan wrote:
> > > Chris R. Miller Wrote:
> > > 
> > >> Lars Ivar Igesund wrote:
> > >>> Chris R. Miller wrote:
> > >>>> Understand, I'm NOT demanding ANYTHING.
> > >>>>
> > >>>> What is the current state of thought about Multiple Inheritance for classes in D?  I'd like to have that feature, since it'd make some stuff I want to do a bit easier.  Is it not there because it's not worth the effort to implement?  Because it's evil and needs to die (I don't know, some people could possibly be adamantly anti-MI)?
> > >>> This is actually the reason, not the adamantly anti-MI part, just that MI is evil and that is well acknowledged almost everywhere. You will find good argumentation against it if you look, too.
> > >> Looking at superdan's message, gee whiz, that didn't take long to find the implementational reasons against it.
> > > 
> > > the sinner tells the truth dood. it's not the implementation reasons. it's the reasons, period. there's no others. with one exception (smalltalk) all languages without fixed field layout do use mi. why? because aside from field layout there is no reason not to, and they already paid the price. this "it's evil" bullshit comes from c++ people tryin' it in wrong ways. just like java 1 zealots yelled all over that generics are crap. then java 5 added (assfucked) generics. guess what. javaots changed their stance. sorry about the argument by comparison fallacy :)
> > 
> > That's humorous coming from you, seeing as how you tauted nothing but implementation reasons.
> > 
> > I know a lot of Java "zealots," and they were never anti-template.  The zealots in your neck of the woods must be more bipolar than mine.
> > 
> > >> Reading about next-gen compilers like LLVM it makes me wonder with all that run-time type inferencing gizmo gadgetry available at virtually no cost, will this make MI (for those who want it) more feasible to implement?  Hmm, a curious possibility to consider.  LLVM is supposed to be wicked fast, too.  My Apple friend tells me that most of OS X's GL stack is built with LLVM for speed.  There might be something to it.
> > > 
> > > i'll make another analogy. with all that research n shit, isn't perpetual motion closer to reality now? hell no. the fact that llvm is fast or smart has nothing to do with basic graph topology. the problem definition makes a solution impossible. this will be broken when someone invents some associative memory shit or some fundamental breakthrough. or when the cost of malloc and indirection becomes small enough to be affordable (solution through tradeoff inversion).
> > 
> > Perpetual motion is slightly different than a new and experimental approach to a compiler.
> > 
> > >>>> I don't know.  I know
> > >>>> I can add a lot with mixins, but I'd just like to know what the state of
> > >>>> the feature is.
> > >>>>
> > >>>> The reason is I was trying to explain how cool D is to some other friends of mine, and they asked about Multiple Inheritance (of classes) and they were sort of put off by it's lack of it.  Then again, he was an Objective-C programmer...  ;-)
> > >>> In the languages where MI is possible, it usually also is possible to not shoot your own foot with some care, in which case it can appear as a powerful feature. But almost everywhere it just is a very bad idea, and you will find it is banned in many projects for languages allowing it (like C++).
> > >> Look long enough and you can find anything.  ;-)
> > >>
> > >> I see your point though.
> > > 
> > > i don't. he has none. he keeps on saying it's a "very bad idea". he could sing it for all i care. how does that make it more pointful.
> > 
> > You continue to amuse me.  First I say I see his point.  You say you don't.  You say he has no point.  Therefore you're absolutely certain that even though someone else sees his concept that it is either false or not there, or both.
> > 
> > >>>> So please don't take offense, since none is meant, I just wanted to know what I could hope for in the future.
> > >>> You should hope you can redesign your application to not need MI ;)
> > >> Yeah, it's trivial to work around it (I did come from Java!) but some bits and pieces seem like it would be better if they could inherit behavior and data, not just a contract.  It could be done through a mixin, but that defeats the polymorphism I want present in the design. And a Mixin and an interface just seems clunky.  What if I do the mixin but forget the interface, or vice-versa?  Yuk!  Though it would give me the option of re-implementing it differently if necessary...  a curious silver lining.
> > > 
> > > the silver lining is in introspection. with it you can define classes that define forwarding functions to other classes. that is almost mi, good enough for many uses.
> > 
> > I don't see how that would restore polymorphism.  Short code example, perhaps?
> 
> I do not know exact how he meant. But I tell how I think it can be. This is how I implement in my project (simplified because I have negative offset).
> 
> class Base1
> {
>     int i1;
>     void f1() {}
> }
> 
> class Base2
> {
>     int i2;
>     void f2() {}
> }
> 
> Goal to define Derived that inherits Base1 and Base2. Derived override both f1 and f2. And contains both i1 and i2. Also Derived implicit convert to Base1 and Base2. Very hard! But can be done. Strategy is derive from one and contain other.
> 
> class Derived : Base1
> {
>     override void f1() {}
>     private Base2 b2;
>     void f2() { return b2.f2; }
> }
> 
> This is first try. I do not put constructor to simplify code. Assume b2 initialized ok. Converts to Base1 but not Base2. Let us fix:
> 
> class Derived : Base1
> {
>     override void f1() {}
>     private Base2 b2;
>     void f2() {}
>     Base2 opImplicitCast() { return b2; }
> }
> 
> Now converts to both. Like inheritance! But see last problem. And most complex. f2 does not override f2 in base. I did it manual but here I use inner classes because they make code simple.
> 
> class Derived : Base1
> {
>     override void f1() {}
>     class Base2Hook : Base2
>     {
>         override void f2() { return outer.f2; }
>     }
>     private Base2Hook b2;
>     void f2() {}
>     Base2 opImplicitCast() { return b2; }
> }
> 
> Now we have all. Derived implements both f1 and f2 and contains i1 and i2. Converts implicit to Base1 and Base2. When you call f2 on the Base2 part correct function is called. It is all good! But it is one more indirection for the Base2 part. Also there is code boring (boilerplate). With introspection it can be generated. So ideal solution is:
> 
> class Derived : Base1
> {
>     override void f1() {}
>     mixin(innerHookForwarder("Base2Hook", "Base2"));
>     private Base2Hook b2;
>     Base2 opImplicitCast() { return b2; }
>     void f2() {}
> }
> 
> Maybe simpler:
> 
> class Derived : Base1
> {
>     mixin(psuedoInheritance("Base2", "b2"));
>     override void f1() {}
>     void f2() {}
> }

cool work dee as always. yeah it's what i meant... i guess eh.

one nit. you should make all thunk functions in Base2Hook final because nobody will inherit Base2Hook. then the thunks are straight calls and can be inlined.

> Now I want to make comment that I hope does not offend some body. I agree that "Multiple Inheritance Is Evil" is very incorrect. Even as joke this answer only...what word... promotes (I think) ignorance and propagates rumors. People agree and laugh and teach other people same mistake. I am sorry if my words are not expressive. I hope the meaning is understood. It is disappointing to see people still use and like this answer but do not want to know the sense. Some part of programming is science and some is social. But we should not mix when possible. Also I hope no offense but it is nice when people talk peaceful. Not fight and bad words. We can have information and good discussion same time. Why one but not an other? It is hard for my poor English to understand message ^_^ Again I hope no offense for any body. If you do not like it please ignore. Thank you, Dee Girl

you are too cool. can't ignore a request from a lady. just hoping you're not a fat n hairy dood in wyoming. i'll try.
August 13, 2008
"Denis Koroskin" wrote
> On Wed, 13 Aug 2008 19:46:51 +0400, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>
>> "superdan" wrote
>>> Steven Schveighoffer Wrote:
>>>
>>>> "superdan" wrote
>>>> > Lars Ivar Igesund Wrote:
>>>> >
>>>> >> Chris R. Miller wrote:
>>>> >>
>>>> >> > Understand, I'm NOT demanding ANYTHING.
>>>> >> >
>>>> >> > What is the current state of thought about Multiple Inheritance
>>>> for
>>>> >> > classes in D?  I'd like to have that feature, since it'd make some
>>>> >> > stuff
>>>> >> > I want to do a bit easier.  Is it not there because it's not worth
>>>> >> > the
>>>> >> > effort to implement?  Because it's evil and needs to die (I don't
>>>> >> > know,
>>>> >> > some people could possibly be adamantly anti-MI)?
>>>> >>
>>>> >> This is actually the reason, not the adamantly anti-MI part, just
>>>> that
>>>> >> MI
>>>> >> is
>>>> >> evil and that is well acknowledged almost everywhere. You will find
>>>> >> good
>>>> >> argumentation against it if you look, too.
>>>> >
>>>> > appeal to authority. appeal to ridicule. appeal to the majority. all
>>>> in
>>>> > one sentence. wow. at least could you space out your fallacies a bit more.
>>>> >
>>>> > the man has kindly asked a sensible question. he deserves a good
>>>> > answer.
>>>> > if u can't give one just don't reply. this is just ignorance.
>>>>
>>>> This kind of bullying bullshit does nothing to further communication,
>>>> or
>>>> help anyone in the least.  You've managed to call many of the brightest
>>>> developers for D idiots, usually based on useless crap like this (which
>>>> has
>>>> no bearing on anything).  So shut the fuck up.
>>>
>>> or what, u gonna kick my ass. relax. you can always block me. (but hold
>>> onto that a bit more. dee's plea is just too cool.) my post did further
>>> communication. it exposed the hackneyed "mi is evil" shit... i mean
>>> poop.
>>> (damn.) it may have helped someone. you know what i like about walter.
>>> when he doesn't know something he is open in admitting it. for that
>>> alone
>>> i'd wash his feet. i didn't call the poster any name. but that
>>> particular
>>> post was bull... i mean crap and i just said it. the fact that the post
>>> sucked bears nothing on the fact that he's good or anything. even worse,
>>> if he's good then why would he use his goodwill to get away with
>>> statements like that. they only reveal ignorance and attempt at
>>> continuing
>>> ignorance because it puts a stigma on anyone investigating mi. it's
>>> silly
>>> we need to still talk about it. now shall we just move on to something
>>> technical.
>>
>> I don't want to block you.  You have some good things to say (although
>> colorful).  Just can it with the "what you said is stupid, so don't post
>> here"  It makes tentative posters not want to post for fear of being
>> ridiculed (not me BTW :) )  Some of them might have interesting things to
>> say.  If you want to argue against someone's point, argue the point
>> (which
>> you did later, and I found it interesting, although my personal
>> experience
>> with MI (on C++) is that it sucks, and should never be used).
>>
>> What Lars said basically is that many people don't like MI, and you can
>> find
>> proof of that (people don't like it) if you search online.  This is the
>> reason Walter doesn't implement it, because he's in that camp.  I think
>> that
>> is a reasonable answer to the question given.
>>
>> It's sort of like most the reasons Walter gives for everything new he
>> comes
>> out with: "X is fundamentally broken in C++".  Substitute fundamentally
>> broken with evil, substitute threading, const, etc. for X.  Can't say I
>> always disagree, but his proof is certainly lacking ;)
>>
>>>> > interface Customer
>>>> > {
>>>> >    string ssn();
>>>> >    string name();
>>>> >    string uniqueName() { return name ~ "(ssn: " ~ ssn ~ ")"; }
>>>> > }
>>>> >
>>>> > so uniqueName formats a specific way. a descendant can choose to
>>>> change
>>>> > that or just use the default. no idea why walt chose to disallow
>>>> that.
>>>> > walt?
>>>>
>>>> What do you pass as the 'this' pointer?  When you call a function on an
>>>> interface, the compiler uses the offset of an interface to the 'this'
>>>> pointer to get to the object, but in this case, there is no object, so
>>>> what
>>>> does the compiler do to call the ssn() and name() functions while
>>>> implementing this function?
>>>
>>> i'm unclear about this so maybe it ain't as easy as i thought.
>>> but i'm thinking the same problem goes for the global string
>>> uniqueName(Customer c) { return c.name ~ "(ssn: " ~ c.ssn ~ ")"; }
>>
>> Not the same as the above problem, because the vtable layout for
>> Customer is
>> always the same.  The name() function expects a pointer to the object,
>> and
>> the implementation knows everything about the object including the
>> vtable.
>> The problem with putting the implementation in the interface is that a
>> member function gets a pointer to the *object* not the *interface*.  In
>> your
>> new example, the 'c' parameter is a pointer to the interface, so that
>> problem doesn't exist.
>>
>>> a pointer to this function should be put in the vtable if the object
>>> does
>>> not implement it.
>>
>> That is fine for calling the function, but not for what to do when
>> compiling
>> it.
>>
>>>
>>>> If you pass the interface pointer as the 'this' pointer, then how do
>>>> you
>>>> override it in an Object that implements the interface?  The function
>>>> in
>>>> the
>>>> concrete class can't be passed the interface pointer, so you can't
>>>> really
>>>> override it.
>>>
>>> that pretty much kills what i wrote above eh. but thunking will take
>>> care
>>> of it. if there's no impl in an object put a pointer to a thunk that
>>> adjusts the pointer (from obj to interface) and calls the default impl
>>> with the adjusted pointer. the latter is a direct call which makes it
>>> fast.
>>
>> Hm... I think this would work actually, as I think this is a runtime
>> lookup.
>> This sounds like a reasonable tradeoff, and having the final modifier if
>> you
>> want it to be quicker (I think the compiler can statically do the thunk
>> if
>> you know the concrete object type).  Actually, it would have to do a
>> thunk
>> for a derived interface, even if you put final on it, as it can't always
>> know the offset between 2 interfaces in a particular object (or can it?).
>>
>> Perhaps someone with better knowledge of the way interfaces work could
>> tell
>> if it would be possible?
>>
>> -Steve
>>
>>
>
> I use MI often and have positive experience with it. One good pattern that
> I use is the Intrusive container.
> Suppose you have an item that you want to store in a list. Unfortunately,
> putting stuff into the single- or double-linked list leads to a memory
> allocation (unless some pool is used). Sometimes it is desirable to put
> next and prev elements into the item itself, so that no memory allocation
> is ever needed. Besides, now you can easily say whether an item is stored
> in any container. This can be implemented via inheritance:
>
> class IntrusiveContainerNode(T)
> {
>     alias T ValueType;
>     package T next;
>     package T prev;
> }
>
> class IntrusiveContainer(TNode)
> {
>     alias TNode.ValueType ValueType;
>
>     void add(ValueType value);
>     void remove(ValueType value);
> }
>
> class MyClass : public Node!(MyClass)
> {
>    // ...
> }
>
> This imposes the restriction that an item can be stored in 1 container at a time. However, you can subclass twise in order to be storable in different containers:
>
> typedef EventOneListener IntrusiveContainerNode;
> typedef EventTwoListener IntrusiveContainerNode;
>
> class MyClass : EventOneListener!(MyClass), EventTwoListener!(MyClass)
> {
>     // ...
> }
>
> MyClass instance = new MyClass();
> eventOneListeners.add(instance);
> eventTwoListeners.add(instance);
>
> It is currently impossible to implement this approach using mixins (due to a bug I'm yet to submit).

I think you can do this without multiple inheritance:

class MyClass
{
   IntrusiveContainerNode!(MyClass) eventOne, eventTwo;
}

If you make IntrusiveContainerNode a struct, then there is no extra memory allocation necessary.

What is wrong with a solution like that?

-Steve


August 13, 2008
"lurker" wrote
>I hate to even think of it but on this one I am with Superdan. Don't get me wrong I think he is the worst scar this group has. I think he has a real problem with the way he treats people and I wouldn't want to be his coworker or neighbor. Most of his posts are so vile I feel like puking when I read them and I blocked him a long time ago. In this thread I saw his posts in quotes and I almost wish I didn't. But I have to say if he had minimal skills at writing he would of won this argument hands down.
>
> I for one was firmly in the "mi is evil" camp on unclear grounds of ambiguity. Lars feel-good post only inforced that. Now my understanding has changed. (Many thanks especially to Dee Girl.)
>
> Most disappointing is one thing. When Lars answered to Superdan in a civilized manner he had an excellent opportunity at showing his class. But he missed it by neither affirming nor denying he knew about the layout problem. That leaves us facing the uncomfortable possibility that he didn't know about it but he did not have the strength to admit it.

I think you completely misunderstood the original question along with Lars' answer.  A simple question was asked.  Why does D not have Multiple inheritance.  A simple answer was given.  Because many people don't like it, including the author (and me incidentally).  What more explaining is necessary from someone who has observed this?

It's like if I said to Lars "I don't like pizza" (which I actually love, but that's beside the point).  And Chris asks a group of people, "why doesn't Steve eat pizza?  Is it because he doesn't like it?", and Lars says "Yes, because he doesn't like it.  Many people don't like it", and you cry foul and tell him off and he should not answer questions unless he *knows* the details.

All this is really actually kind of amusing, we are arguing about stuff that really has no bearing on anything :)

-Steve