www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Multiple Inheritance of Classes

reply "Chris R. Miller" <lordSaurontheGreat gmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable

Understand, I'm NOT demanding ANYTHING.

What is the current state of thought about Multiple Inheritance for=20
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=20
effort to implement?  Because it's evil and needs to die (I don't know,=20
some people could possibly be adamantly anti-MI)?  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=20
friends of mine, and they asked about Multiple Inheritance (of classes)=20
and they were sort of put off by it's lack of it.  Then again, he was an =

Objective-C programmer...  ;-)

So please don't take offense, since none is meant, I just wanted to know =

what I could hope for in the future.
Aug 11 2008
next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
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.
 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++).
 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 ;) -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Aug 12 2008
next sibling parent reply superdan <super dan.org> writes:
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. below's an attempt at an answer. first i repeat what is already known. d does do multiple inheritance thru interfaces. it doesn't do multiple inheritance of implementation. better put doesn't do multiple inheritance of data. why? simple. d is a fixed layout language. means that the offset of any data member within the object is known during compilation. with mi it is impossible to lay out objects in a fixed layout. unless you do it the nonsensical way c++ does. at least you can't lay out with 1-dimensional memory. (i've done vlsi design and sure as shit 2-dim helps a lot. but a lot more could be done with 3-dim. i remember only adding two layers was a huge deal.) with mi from n classes you'd need n-dimensional ram. that's why only simple inheritance is possible with 1-dimensional ram. if u want fixed layout that is. (now that i got into it there was a guy who did 2-class inheritance by storing stuff at positive and negative offsets, thus adding a 2nd dimension.) mi of interfaces is a good thing and putting an int in an interface does not make it evil. just makes it impossible to lay out. 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?
 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++).
 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 ;) -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango

"blah blah blah more contentless uninformative fallacious blabber blah i can't believe i'm still reading this blah blah". sorry dood but this is all i'm seeing.
Aug 12 2008
next sibling parent reply BCS <ao pathlink.com> writes:
Reply to superdan,

 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)?
 

that MI is evil and that is well acknowledged almost everywhere. You will find good argumentation against it if you look, too.


Always a good idea if, like most people, you don't plan on /becoming/ an authority
 appeal to ridicule. appeal to the majority.

Both reasonable if enough people are doing the ridicule (95% majority?), again with the disclaimer for the occasional expert/academic that most of us (walter excluded) don't have anywhere near the time to become.
 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.
 

I think that was a good answer to the question "Why doesn't D have MI?"
 below's an attempt at an answer.

The below is a reasonable answer to "Justify D's lack of MI." or "What is the rational for D's not having MI?" Those are different questions that what Lars was going for.
 
 first i repeat what is already known. d does do multiple inheritance
 thru interfaces.

Is interfaces MI? That is debatable because, as you point out, there is a huge difference between it and MI->data & MI->implementation.
 it doesn't do multiple inheritance of implementation.
 better put doesn't do multiple inheritance of data.

[...]
 putting an int in an interface does not
 make it evil. just makes it impossible to lay out.
 

In this context "evil" is a relative term. Nothing in programing it truly evil... Well maybe C++. http://www-users.cs.york.ac.uk/~susan/joke/cpp.htm
 interfaces could implement functions. that does make a lot of sense.
 example:
 
 interface Customer
 {
 string ssn();
 string name();
 string uniqueName() { return name ~ "(ssn: " ~ ssn ~ ")"; }
 }

Yeah, I've wanted that, OTOH it might get tricky to implement because of the mechanics of interfaces. option 1: uniqueName becomes a implicit mixin that gets expanded per class code bloat, etc. but that's what we do manually anyway. option 2: uniqueName has a single implementation that is shared by all implementing classes This is an ugly solution because the only way to make that work would be to have this inside uniqueName be an interface reference, however as things stand interface references are turned into object references (by offsetting the pointer) on interface calls. Work around for this include doing this inside the functions and having an interface version and a non interface version of each function (not viable for closed source) or using little shells everywhere (errr, yuck, but it would work)
 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?
 

Aug 12 2008
parent reply superdan <super dan.org> writes:
BCS Wrote:

 Reply to superdan,
 
 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)?
 

that MI is evil and that is well acknowledged almost everywhere. You will find good argumentation against it if you look, too.


Always a good idea if, like most people, you don't plan on /becoming/ an authority

hard time defending that post eh. he appealed to his own authority "this is the reason". then to an emotional word. then to majority. see also http://en.wikipedia.org/wiki/Appeal_to_authority tho invoking wikipedia may also be a fallacy :)
 appeal to ridicule. appeal to the majority.

Both reasonable if enough people are doing the ridicule (95% majority?), again with the disclaimer for the occasional expert/academic that most of us (walter excluded) don't have anywhere near the time to become.

i don't find either particularly reasonable. http://en.wikipedia.org/wiki/Appeal_to_ridicule http://en.wikipedia.org/wiki/Argumentum_ad_populum. if you don't have the time to become an expert just let walter or some expert answer. that post reveals zero knowledge on the subject. merely a perpetuation of the "it's evil" heard from someone else and ingested noncritically. after "don't do it!!! it's evil!!!" all i can expect next is "keep the faith!!!" fuck man.
 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.
 

I think that was a good answer to the question "Why doesn't D have MI?"

"it's evil" is a good answer? cut the shit man. why is it evil again? your critical reasoning filter ever questioned that assertion?
 below's an attempt at an answer.

The below is a reasonable answer to "Justify D's lack of MI." or "What is the rational for D's not having MI?" Those are different questions that what Lars was going for.

pardon me if i'm dense but i have a hard time distinguishing between the two. and pardon me if i continue to think "it's evil" is mere oxshit.
 first i repeat what is already known. d does do multiple inheritance
 thru interfaces.

Is interfaces MI? That is debatable because, as you point out, there is a huge difference between it and MI->data & MI->implementation.

it's not debatable. interfaces are inheritance. they satisfy the definition. (substitution principle.) if you implement multiple interfaces you do mi. case closed. to summarize: d does mi of interface but not mi of data and not mi of implementation. they are different flavors of shit but that does not make interfaces mi debatable.
 it doesn't do multiple inheritance of implementation.
 better put doesn't do multiple inheritance of data.

[...]
 putting an int in an interface does not
 make it evil. just makes it impossible to lay out.
 

In this context "evil" is a relative term. Nothing in programing it truly evil... Well maybe C++. http://www-users.cs.york.ac.uk/~susan/joke/cpp.htm
 interfaces could implement functions. that does make a lot of sense.
 example:
 
 interface Customer
 {
 string ssn();
 string name();
 string uniqueName() { return name ~ "(ssn: " ~ ssn ~ ")"; }
 }

Yeah, I've wanted that, OTOH it might get tricky to implement because of the mechanics of interfaces. option 1: uniqueName becomes a implicit mixin that gets expanded per class code bloat, etc. but that's what we do manually anyway. option 2: uniqueName has a single implementation that is shared by all implementing classes This is an ugly solution because the only way to make that work would be to have this inside uniqueName be an interface reference, however as things stand interface references are turned into object references (by offsetting the pointer) on interface calls. Work around for this include doing this inside the functions and having an interface version and a non interface version of each function (not viable for closed source) or using little shells everywhere (errr, yuck, but it would work)

nothing that walt can't do.
Aug 12 2008
parent BCS <ao pathlink.com> writes:
Reply to superdan,

 BCS Wrote:
 
 appeal to ridicule. appeal to the majority.
 

majority?), again with the disclaimer for the occasional expert/academic that most of us (walter excluded) don't have anywhere near the time to become.

http://en.wikipedia.org/wiki/Appeal_to_ridicule

OK I got that backwards: appeal to ridicule != lots of people ridicule it
 http://en.wikipedia.org/wiki/Argumentum_ad_populum. if you don't have
 the time to become an expert just let walter or some expert answer.
 that post reveals zero knowledge on the subject. merely a perpetuation
 of the "it's evil" heard from someone else and ingested noncritically.
 after "don't do it!!! it's evil!!!" all i can expect next is "keep the
 faith!!!" fuck man.
 

I'm not saying either is a good proof or even a strong argument, but if you don't have time to form your own opinion (and like it or not most of the time you don't) both work reasonably well untill you do have time. And in this cases I think it is more of an opinion summery that a proof or argument.
 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.
 

MI?"

your critical reasoning filter ever questioned that assertion?
 below's an attempt at an answer.
 

"What is the rational for D's not having MI?" Those are different questions that what Lars was going for.

the two. and pardon me if i continue to think "it's evil" is mere oxshit.

the one answer is like saying "don't drive over 35 MPH on that street because it's illegal" the other answer is like saying "it is illegal to drive over 35 MPH because there are small children playing there" Another way of looking at it would be that the first is like saying "I did B after reading the paper 'A is a bad Idea' " and the second is the paper it's self.
 first i repeat what is already known. d does do multiple inheritance
 thru interfaces.
 

is a huge difference between it and MI->data & MI->implementation.

definition. (substitution principle.) if you implement multiple interfaces you do mi. case closed. to summarize: d does mi of interface but not mi of data and not mi of implementation. they are different flavors of shit but that does not make interfaces mi debatable.

OK fine, pick a word (I'll use ___) that applyes to the stuff D dosn't do and not to the stuff it does. The OP wants to talk about why D dosn't have ___. Talking about if ___ is MI is realy boring so lets not.
 Yeah, I've wanted that, OTOH it might get tricky to implement because
 of the mechanics of interfaces.
 


 


I'll have to go with "He has better thigns to do" on that one.
Aug 12 2008
prev sibling next sibling parent reply Dee Girl <deegirl noreply.com> writes:
superdan Wrote:
 below's an attempt at an answer.
 
 first i repeat what is already known. d does do multiple inheritance thru
interfaces. it doesn't do multiple inheritance of implementation. better put
doesn't do multiple inheritance of data. why? simple. d is a fixed layout
language. means that the offset of any data member within the object is known
during compilation. with mi it is impossible to lay out objects in a fixed
layout. unless you do it the nonsensical way c++ does. at least you can't lay
out with 1-dimensional memory. (i've done vlsi design and sure as shit 2-dim
helps a lot. but a lot more could be done with 3-dim. i remember only adding
two layers was a huge deal.) with mi from n classes you'd need n-dimensional
ram. that's why only simple inheritance is possible with 1-dimensional ram. if
u want fixed layout that is. (now that i got into it there was a guy who did
2-class inheritance by storing stuff at positive and negative offsets, thus
adding a 2nd dimension.) mi of interfaces is a good thing and putting an int in
an interface does not make it evil. just makes it impossible to lay out.

I am impress! The above is true word with word. Without one word maybe ^_^. I did a semester project for data layout with maximum efficient. It is hard! Maybe you talk about this paper: Bidirectional Object Layout. http://citeseer.ist.psu.edu/myers95bidirectional.html There is also follow up paper: Two-Directional Bidimensional Object Layout. http://citeseer.ist.psu.edu/670868.htm Maybe you are talk about the second because it has the negative offset. Thank you, Dee Girl
Aug 12 2008
parent superdan <super dan.org> writes:
Dee Girl Wrote:

 superdan Wrote:
 below's an attempt at an answer.
 
 first i repeat what is already known. d does do multiple inheritance thru
interfaces. it doesn't do multiple inheritance of implementation. better put
doesn't do multiple inheritance of data. why? simple. d is a fixed layout
language. means that the offset of any data member within the object is known
during compilation. with mi it is impossible to lay out objects in a fixed
layout. unless you do it the nonsensical way c++ does. at least you can't lay
out with 1-dimensional memory. (i've done vlsi design and sure as shit 2-dim
helps a lot. but a lot more could be done with 3-dim. i remember only adding
two layers was a huge deal.) with mi from n classes you'd need n-dimensional
ram. that's why only simple inheritance is possible with 1-dimensional ram. if
u want fixed layout that is. (now that i got into it there was a guy who did
2-class inheritance by storing stuff at positive and negative offsets, thus
adding a 2nd dimension.) mi of interfaces is a good thing and putting an int in
an interface does not make it evil. just makes it impossible to lay out.

I am impress! The above is true word with word. Without one word maybe ^_^. I did a semester project for data layout with maximum efficient. It is hard! Maybe you talk about this paper: Bidirectional Object Layout. http://citeseer.ist.psu.edu/myers95bidirectional.html There is also follow up paper: Two-Directional Bidimensional Object Layout. http://citeseer.ist.psu.edu/670868.htm Maybe you are talk about the second because it has the negative offset. Thank you, Dee Girl

cool dee. where do you pull'em from. i vaguely think i was talking about the second one, the israel dood, but then i'm just guessin' (and braggin').
Aug 12 2008
prev sibling next sibling parent reply "Manfred_Nowak" <svv1999 hotmail.com> writes:
superdan wrote:

 with mi it is impossible to lay out objects in a fixed layout.
 unless you do it [...]

I do not understand this. Do you mean, that it is impossible or do you mean one can do a fixed layout _with_ mi? Then: given that "D is a systems programming language", how would one implement an efficient system, for which a requirement for mi exists, in D? -manfred -- Maybe some knowledge of some types of disagreeing and their relation can turn out to be useful: http://blog.createdebate.com/2008/04/07/writing-strong-arguments/
Aug 12 2008
parent reply superdan <super dan.org> writes:
Manfred_Nowak Wrote:

 superdan wrote:
 
 with mi it is impossible to lay out objects in a fixed layout.
 unless you do it [...]

I do not understand this. Do you mean, that it is impossible or do you mean one can do a fixed layout _with_ mi?

man there's a ton to explain and then some more. i got work n shit to do but let me try. stay with me ok? take a pen and paper and draw this shit. simple hierarchy: class a { ubyte x[100]; } class b : a { ubyte y[200]; } class c : a { ubyte z[500]; } let's lay a and b out. you could lay both out with the base first or last. you must be consistent. can't hand-pick your guesses. say you decide base first: b : x y c : x z so far so good. these decisions were made. can't be rethought later. because it's fixed layout, remember. put'em in ur pocket. now comes this motherfucker: class bc : b, c {} now you want b and c to be subobjects of bc with the same layout of b and c alone. so for bc there's only two cut and dried choices. either b then c or c then b. let's choose the first and unroll that shit: bc : [ x y x z ] but you don't want that because there are two xs where there should be one. see now how topological layout of a dag on a 1-dimensional line (linear memory) can't cut the shit. but say you hand pick this example and make it work: b : [ y z ] c : [ z x ] bc : [ y z x ] youza that works. but then if you do this: class d : b, bc {} class e : d, bc {} that grandmotherfucks the entire situation. there's no way to lay that shit out. unless you know the hierarchy in advance. which is unreasonable. and you also have to allow for holes in objects. that also sucks ass.
 Then: given that "D is a systems programming language", how would one 
 implement an efficient system, for which a requirement for mi exists, 
 in D?

good question. i have two thoughts. one is with stacked templates. that allows you not mi but stacked si. class a(t = Object) : t {} class b(t = Object) : t {} class ab : b!(a!()) {} that way you draw your own layout on a line. it sucks that d doesn't allow a to mean a!(). the latter looks like shit. (i mean shit in a bad way.) but that's not true mi because different as and bs come templated with different arguments. they mean nothing to one another. that's only good for inheritance of implementation shit. second thought. i think introspection may be the shit. (here i mean shit in a good way.) use classic layout for one base. then use indirection thru refs for the layout of the rest. introspection plops the forwarding functions. opImplicitCast adds seasoning for taste. this looks like some std.typecons shit.
Aug 12 2008
next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
superdan Wrote:

 Manfred_Nowak Wrote:
 
 superdan wrote:
 
 with mi it is impossible to lay out objects in a fixed layout.
 unless you do it [...]

I do not understand this. Do you mean, that it is impossible or do you mean one can do a fixed layout _with_ mi?

man there's a ton to explain and then some more. i got work n shit to do but let me try. stay with me ok? take a pen and paper and draw this shit. simple hierarchy: class a { ubyte x[100]; } class b : a { ubyte y[200]; } class c : a { ubyte z[500]; } let's lay a and b out. you could lay both out with the base first or last. you must be consistent. can't hand-pick your guesses. say you decide base first: b : x y c : x z so far so good. these decisions were made. can't be rethought later. because it's fixed layout, remember. put'em in ur pocket. now comes this motherfucker: class bc : b, c {} now you want b and c to be subobjects of bc with the same layout of b and c alone. so for bc there's only two cut and dried choices. either b then c or c then b. let's choose the first and unroll that shit: bc : [ x y x z ] but you don't want that because there are two xs where there should be one. see now how topological layout of a dag on a 1-dimensional line (linear memory) can't cut the shit. but say you hand pick this example and make it work: b : [ y z ] c : [ z x ] bc : [ y z x ] youza that works. but then if you do this: class d : b, bc {} class e : d, bc {} that grandmotherfucks the entire situation. there's no way to lay that shit out. unless you know the hierarchy in advance. which is unreasonable. and you also have to allow for holes in objects. that also sucks ass.
 Then: given that "D is a systems programming language", how would one 
 implement an efficient system, for which a requirement for mi exists, 
 in D?

good question. i have two thoughts. one is with stacked templates. that allows you not mi but stacked si. class a(t = Object) : t {} class b(t = Object) : t {} class ab : b!(a!()) {} that way you draw your own layout on a line. it sucks that d doesn't allow a to mean a!(). the latter looks like shit. (i mean shit in a bad way.) but that's not true mi because different as and bs come templated with different arguments. they mean nothing to one another. that's only good for inheritance of implementation shit. second thought. i think introspection may be the shit. (here i mean shit in a good way.) use classic layout for one base. then use indirection thru refs for the layout of the rest. introspection plops the forwarding functions. opImplicitCast adds seasoning for taste. this looks like some std.typecons shit.

So why not just dissalow diamond-pattern MI?
Aug 12 2008
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Robert Fraser" <fraserofthenight gmail.com> wrote in message 
news:g7surd$21u0$1 digitalmars.com...

 So why not just dissalow diamond-pattern MI?

A singly-rooted object hierarchy like D has precludes that from being possible. Everything will ultimately go back to Object.
Aug 12 2008
parent reply superdan <super dan.org> writes:
Jarrett Billingsley Wrote:

 "Robert Fraser" <fraserofthenight gmail.com> wrote in message 
 news:g7surd$21u0$1 digitalmars.com...
 
 So why not just dissalow diamond-pattern MI?

A singly-rooted object hierarchy like D has precludes that from being possible. Everything will ultimately go back to Object.

would work if Object had absolutely no state. but it has the vptr and the synchronization shit. that fucks the plan right there.
Aug 12 2008
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"superdan" <super dan.org> wrote in message 
news:g7t4cr$2efv$1 digitalmars.com...
 Jarrett Billingsley Wrote:

 "Robert Fraser" <fraserofthenight gmail.com> wrote in message
 news:g7surd$21u0$1 digitalmars.com...

 So why not just dissalow diamond-pattern MI?

A singly-rooted object hierarchy like D has precludes that from being possible. Everything will ultimately go back to Object.

would work if Object had absolutely no state. but it has the vptr and the synchronization shit. that fucks the plan right there.

Seriously, learn to type like a normal person or just shut the fuck up. I've had it up to here.
Aug 12 2008
prev sibling next sibling parent reply Yigal Chripun <yigal100 gmail.com> writes:
superdan wrote:
 Manfred_Nowak Wrote:
 
 superdan wrote:
 
 with mi it is impossible to lay out objects in a fixed layout. 
 unless you do it [...]

you mean one can do a fixed layout _with_ mi?

man there's a ton to explain and then some more. i got work n shit to do but let me try. stay with me ok? take a pen and paper and draw this shit. simple hierarchy: class a { ubyte x[100]; } class b : a { ubyte y[200]; } class c : a { ubyte z[500]; } let's lay a and b out. you could lay both out with the base first or last. you must be consistent. can't hand-pick your guesses. say you decide base first: b : x y c : x z so far so good. these decisions were made. can't be rethought later. because it's fixed layout, remember. put'em in ur pocket. now comes this motherfucker: class bc : b, c {} now you want b and c to be subobjects of bc with the same layout of b and c alone. so for bc there's only two cut and dried choices. either b then c or c then b. let's choose the first and unroll that shit: bc : [ x y x z ] but you don't want that because there are two xs where there should be one. see now how topological layout of a dag on a 1-dimensional line (linear memory) can't cut the shit. but say you hand pick this example and make it work: b : [ y z ] c : [ z x ] bc : [ y z x ] youza that works. but then if you do this: class d : b, bc {} class e : d, bc {} that grandmotherfucks the entire situation. there's no way to lay that shit out. unless you know the hierarchy in advance. which is unreasonable. and you also have to allow for holes in objects. that also sucks ass.
 Then: given that "D is a systems programming language", how would
 one implement an efficient system, for which a requirement for mi
 exists, in D?

good question. i have two thoughts. one is with stacked templates. that allows you not mi but stacked si. class a(t = Object) : t {} class b(t = Object) : t {} class ab : b!(a!()) {} that way you draw your own layout on a line. it sucks that d doesn't allow a to mean a!(). the latter looks like shit. (i mean shit in a bad way.) but that's not true mi because different as and bs come templated with different arguments. they mean nothing to one another. that's only good for inheritance of implementation shit. second thought. i think introspection may be the shit. (here i mean shit in a good way.) use classic layout for one base. then use indirection thru refs for the layout of the rest. introspection plops the forwarding functions. opImplicitCast adds seasoning for taste. this looks like some std.typecons shit.

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. In another post of yours you referred to adding function bodies to interfaces. Do you have any ideas on how to implement this efficiently? last question: can you explain what do you mean by non fixed layout languages that have MI?
Aug 12 2008
parent reply superdan <super dan.org> writes:
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?
 In another post of yours you referred to adding function bodies to
 interfaces. Do you have any ideas on how to implement this efficiently?

each interface defines a vtable layout. it does not define what the table contains. a class implementing an interface will fill that vtable with its own functions. if a class forgets to fill all slots there's an error because there's nothing to fill that slot with. with me so far? now if an interface defines function bodies, that simply means there are defaults for some of those entries. that's all. if the derived class doesn't fill them they are filled and the compiler calls it a day. (walt please confirm.) now i know everybody and their fave hooker has a pet feature to add to d, but i'd really like that shit in d2. it would raise interface powers to a whole new level. why? because you can define an interface that defines high-level functions that callers can use yet requires the implementers to implement the low-level primitives. i think i saw this shit in herb sutter. he calls it non-virtual idiom or some'n'. that shit is essential for contracts, too. contracts in d are fucked up. it's a cryin' shame. contracts should be on interfaces so they enforce shit on their implementors. as they should. right now only implementors can enforce shit on their own ass. how's that helpful i don't see. interface Stack!(T) { bool empty(); T push() out { enforce(!empty); } T pop() in { enforce(!empty); } T top() in { enforce(!empty); } } now the stack writer not only wishes the implementer does some sensible shit. he also makes sure shit is respected. and if you think of it for a minute you'll see how this kind of requires implementation of functions in interfaces.
 last question: can you explain what do you mean by non fixed layout
 languages that have MI?

clos, python, perl, curl. even javascript. they have non-fixed layout. with hashes mapping names to values and shit. they would have to go out of their way to disallow mi. so they just allow it because "it's not evil". it just costs.
Aug 12 2008
next sibling parent superdan <super dan.org> writes:
superdan Wrote:

 interface Stack!(T)
 {
     bool empty();
     T push() out { enforce(!empty); }
     T pop() in { enforce(!empty); }
     T top() in { enforce(!empty); }
 }

interface Stack!(T) { bool empty(); void push(T t) out { enforce(top() == t); } T pop() in { enforce(!empty); } T top() in { enforce(!empty); } } mah bad.
Aug 12 2008
prev sibling parent reply Yigal Chripun <yigal100 gmail.com> writes:
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit

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)
Aug 13 2008
parent reply superdan <super dan.org> writes:
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.
Aug 13 2008
parent Yigal Chripun <yigal100 gmail.com> writes:
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.


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.
Aug 13 2008
prev sibling parent reply "Manfred_Nowak" <svv1999 hotmail.com> writes:
superdan wrote:

 and you also have to allow for holes in objects

Then it isn't fixed layout alone, but also avoiding slices of unused memory within objects. If you advocate for this under the reason, that this scheme allows for efficient access for members by sparing one indirection, then: why do you accept interfaces? Given that the layout of objects is fixed and without unused slices, interfaces must be able to adapt to the layouts of many different object types. This cannot be done without a mapping known at runtime and therefore has to stay with the object, which in turn would enable MI. -manfred -- Maybe some knowledge of some types of disagreeing and their relation can turn out to be useful: http://blog.createdebate.com/2008/04/07/writing-strong-arguments/
Aug 14 2008
parent superdan <super dan.org> writes:
Manfred_Nowak Wrote:

 superdan wrote:
 
 and you also have to allow for holes in objects

Then it isn't fixed layout alone, but also avoiding slices of unused memory within objects. If you advocate for this under the reason, that this scheme allows for efficient access for members by sparing one indirection, then: why do you accept interfaces?

don't quote me out of context. the `also' came after the whole hierarchy knowledge. that's the real killer.
Aug 14 2008
prev sibling next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
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.


 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.

I took it as a tongue-in-cheek question, and so was my answer. If Chris took offense, I am sorry. I am however happy that you provided a good technical response for once. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Aug 12 2008
parent "Chris R. Miller" <lordSaurontheGreat gmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable

Lars Ivar Igesund 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 t=




 effort to implement?  Because it's evil and needs to die (I don't kn=




 some people could possibly be adamantly anti-MI)?




 is evil and that is well acknowledged almost everywhere. You will fin=



 good argumentation against it if you look, too.


 the man has kindly asked a sensible question. he deserves a good answe=


 if u can't give one just don't reply. this is just ignorance.

I took it as a tongue-in-cheek question, and so was my answer. If Chris=

 offense, I am sorry. I am however happy that you provided a good techni=

 response for once.

You response, Lars, was more or less what I was looking for. It told me = that it wasn't that Walter is absolutely scared of implementing it, but=20 that there's a reason he doesn't. The moment I saw a reply by superdan my first thought was "oh god, not=20 another zillion-message-long study in the ambiguity possible in written=20 English." I was mighty tempted to not read superdan's messages, but=20 through the "colorful" language there was a few bits of substance -=20 mainly an explanation of why it's a difficult thing to implement.
Aug 12 2008
prev sibling next sibling parent reply Benji Smith <dlanguage benjismith.net> writes:
superdan wrote:
 better put doesn't do multiple inheritance of data. why? simple. d is a fixed
layout language. means that the offset of any data member within the object is
known during compilation. with mi it is impossible to lay out objects in a
fixed layout. unless you do it the nonsensical way c++ does. at least you can't
lay out with 1-dimensional memory. (i've done vlsi design and sure as shit
2-dim helps a lot. but a lot more could be done with 3-dim. i remember only
adding two layers was a huge deal.) with mi from n classes you'd need
n-dimensional ram. that's why only simple inheritance is possible with
1-dimensional ram. if u want fixed layout that is. (now that i got into it
there was a guy who did 2-class inheritance by storing stuff at positive and
negative offsets, thus adding a 2nd dimension.) mi of interfaces is a good
thing and putting an int in an interface does not make it evil. just makes it
impossible to lay out.

Which begs the question of why D is a fixed layout language. My impression is that, if MI was a high enough priority, the data layout issues could be easily solved (maybe by having the compiler automatically generate the necessary interfaces and mixins, and using a separate data layout for each inheritance permutation). My understanding of *why* that route wasn't taken is that, from a design perspective, MI creates interface ambiguities that the programmer would usually rather not deal with. For example: class A { public int xyz() { ... } } class B { public int xyz() { ... } } class C : A, B { ... } C c = new C(); c.xyz(); // ambiguous Sure, you could have the programmer explicitly disambiguate which xyz method to call, with something like this: ((A) c).xyz(); But is it really worth it, especially given the compiler gymnastics required to solve the data layout obstacles? My impression has always been that the design consequences of MI in D made it undesirable (that's what people mean when they say that MI is "evil" or "ugly" or any of those other subjective, hyperbolic terms). The implementation hurdles could be overcome if MI was desirable, so it's not an insurmountable technical challenge as superdan's message implies. I could be wrong in my recollection of the history of D, but that's how I remember the discussions from three or four years ago, when MI was a more commonly discussed topic. Mixins (code mixins, not string mixins, which didn't exist yet) were introduced specifically as a mechanism to avoid MI, avoiding code duplication without resorting to the ambiguities of MI. --benji
Aug 12 2008
next sibling parent Dee Girl <deegirl noreply.com> writes:
Benji Smith Wrote:

 superdan wrote:
 better put doesn't do multiple inheritance of data. why? simple. d is a fixed
layout language. means that the offset of any data member within the object is
known during compilation. with mi it is impossible to lay out objects in a
fixed layout. unless you do it the nonsensical way c++ does. at least you can't
lay out with 1-dimensional memory. (i've done vlsi design and sure as shit
2-dim helps a lot. but a lot more could be done with 3-dim. i remember only
adding two layers was a huge deal.) with mi from n classes you'd need
n-dimensional ram. that's why only simple inheritance is possible with
1-dimensional ram. if u want fixed layout that is. (now that i got into it
there was a guy who did 2-class inheritance by storing stuff at positive and
negative offsets, thus adding a 2nd dimension.) mi of interfaces is a good
thing and putting an int in an interface does not make it evil. just makes it
impossible to lay out.

Which begs the question of why D is a fixed layout language. My impression is that, if MI was a high enough priority, the data layout issues could be easily solved (maybe by having the compiler automatically generate the necessary interfaces and mixins, and using a separate data layout for each inheritance permutation).

I think this is very correct. But without "easy" word in there ^_^. Without entire hierarchy knowledge you can not make good layout. And I think that limits very much the power of language. I know language Dylan. It has sealed domains. They mean an entire hierarchy that is known. One author of Dylan gave a talk at the Uni that I saw. He explained how sealed domains allow good layout. Also faster function dispatch because all possible functions are known. But I agree. Multiple inheritance is not important so much to justify the cost. So languages work without it. But it is not evil! ^_^
 My understanding of *why* that route wasn't taken is that, from a design 
 perspective, MI creates interface ambiguities that the programmer would 
 usually rather not deal with. For example:
 
 class A { public int xyz() { ... } }
 
 class B { public int xyz() { ... } }
 
 class C : A, B { ... }
 
 C c = new C();
 c.xyz(); // ambiguous
 
 Sure, you could have the programmer explicitly disambiguate which xyz 
 method to call, with something like this:
 
 ((A) c).xyz();
 
 But is it really worth it, especially given the compiler gymnastics 
 required to solve the data layout obstacles?
 
 My impression has always been that the design consequences of MI in D 
 made it undesirable (that's what people mean when they say that MI is 
 "evil" or "ugly" or any of those other subjective, hyperbolic terms). 
 The implementation hurdles could be overcome if MI was desirable, so 
 it's not an insurmountable technical challenge as superdan's message 
 implies.

I am sorry. But I think this understanding is mistaken. The ambiguity problem is also with interfaces. They require implementing all functions. Then it is OK to ask to override all ambiguous functions in a MI scheme. It is not worse then interfaces. To call you can use classic member access A.xyz or B.xyz. Superdan is correct. The problem with state is insurmountable. I did not know what it means and I look it up now ^_^. It is. I implemented it and it is not about what function to call or ambiguous. It is always data data data. Where can you put data to make every body happy. Multiple inheritance effects very much the entire store model. You lose "prefix property" and then everything is much complicated!
 I could be wrong in my recollection of the history of D, but that's how 
 I remember the discussions from three or four years ago, when MI was a 
 more commonly discussed topic. Mixins (code mixins, not string mixins, 
 which didn't exist yet) were introduced specifically as a mechanism to 
 avoid MI, avoiding code duplication without resorting to the ambiguities 
 of MI.

I am sure Walter knows perfectly. It is about data. I am sorry but I disagree ambiguity is major problem or problem at all. Sorry, Dee Girl
Aug 12 2008
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Benji Smith wrote:
 superdan wrote:
 better put doesn't do multiple inheritance of data. why? simple. d is 
 a fixed layout language. means that the offset of any data member 
 within the object is known during compilation. with mi it is 
 impossible to lay out objects in a fixed layout. unless you do it the 
 nonsensical way c++ does. at least you can't lay out with 
 1-dimensional memory. (i've done vlsi design and sure as shit 2-dim 
 helps a lot. but a lot more could be done with 3-dim. i remember only 
 adding two layers was a huge deal.) with mi from n classes you'd need 
 n-dimensional ram. that's why only simple inheritance is possible with 
 1-dimensional ram. if u want fixed layout that is. (now that i got 
 into it there was a guy who did 2-class inheritance by storing stuff 
 at positive and negative offsets, thus adding a 2nd dimension.) mi of 
 interfaces is a good thing and putting an int in an interface does not 
 make it evil. just makes it impossible to lay out.

Which begs the question of why D is a fixed layout language. My impression is that, if MI was a high enough priority, the data layout issues could be easily solved (maybe by having the compiler automatically generate the necessary interfaces and mixins, and using a separate data layout for each inheritance permutation).

Accessing members in a fixed-layout class is easy: *(this + offset). And the offset is known at compile time, so it's probably one instruction. (Granted, the member is probably in cache rather than a register if you're doing this, so it'll take more time than that anyway.) If you don't do that, you need to use some sort of indirection. And you have to regenerate the mapping from identifier to offset for each class in the hierarchy. This is slower, albeit not incredibly slow, and it's more work, and without multiple inheritance, why bother? Also, casting with some arbitrary layout might mean generating a new class, effectively, unless you keep your mapping on the classinfo of the object (which costs extra page faults) or each object (which makes your objects larger). There's little or no advantage to a dynamic layout in this case.
Aug 13 2008
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"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
Aug 13 2008
next sibling parent reply superdan <super dan.org> writes:
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.
Aug 13 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"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
Aug 13 2008
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"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



 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


 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

 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

 that or just use the default. no idea why walt chose to disallow

 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
Aug 13 2008
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Denis Koroskin" wrote
 On Wed, 13 Aug 2008 20:52:24 +0400, Steven Schveighoffer 
 <schveiguy yahoo.com> wrote:

 "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



 classes in D?  I'd like to have that feature, since it'd make



 stuff
 I want to do a bit easier.  Is it not there because it's not



 the
 effort to implement?  Because it's evil and needs to die (I



 know,
 some people could possibly be adamantly anti-MI)?

This is actually the reason, not the adamantly anti-MI part, just


 MI
 is
 evil and that is well acknowledged almost everywhere. You will


 good
 argumentation against it if you look, too.

appeal to authority. appeal to ridicule. appeal to the majority.

in
 one sentence. wow. at least could you space out your fallacies a

 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

 that or just use the default. no idea why walt chose to disallow

 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

1) Functionality. You loose an opportunity to iterate over elements of the container. It can be resolved by extending the IntrusiveContainerNode class to store a thisPtr as well (4 more bytes per instance):

How does C++ MI do it? I mean, if you have a pointer to class X, which is the second base class of (layout-wise), how does one find the pointer to Y? It can't be a standard offset because you have no idea how many base classes are there. I would think that MI has to store the offset anyways.
 2) Readability. In addition to the complexity above, you are now forced to 
 write the following code instead:
 eventOneListeners.add(&instance.eventOne);
 eventTwoListeners.add(&instance.eventTwo);

I guess :) It seems more clear this way to me. what if you have 3 event listener containers, but you only ever put an element into 2 of them at a time? Should you always store 3 IntrusiveContainerNode base classes in all elements?
 3) Usability. You have to remember all the names like "eventOne", 
 "eventTwo" or whatever name you give to the node. In some cases users are 
 forced to stick with some predefined names, code becomes templated and 
 losses virtuality. The following code shows the issues:

 class UpdateDispatcher
 {
     void addEventListener(T)(T listener) // a template. non-virtual.
     {
         updateContainer.add(listener.updateEvent); // updateEvent is a 
 predefined name.
         //All the classes that want to recieve an Update should have a 
 public "updateEvent" field in their body!
     }
 }

Then use a hashtable to look up the lists (with an id supplied by the list as the key). You can have as many lists as you want. If you are looking for virtuality, or non-naming conventions (i.e. extendability), then why is your code specifically tuned to the implementation (i.e. only 2 specific lists)? You can pass in the member name as a mixin string if necessary.
 4) Performance. Additional pointer dereference (node->thisPtr->data) 
 introduced (minor one, but nevertheless).

Again, how does C++ MI do it? I'd guess they have to do the same thing.
 All these issues make the idiom unusable.

Nothing here conveys that to me. What I see is that MI is possible in D, but hard to implement. But you are exposing the ugly nature of what MI requires, and that makes you understand more of what is necessary to make MI work. It results in less errors IMO, because you aren't confused why the compiler didn't just take care of it for you , and you have some obscure access violation bug (as was my experience). -Steve
Aug 14 2008
prev sibling parent JAnderson <ask me.com> writes:
Denis Koroskin wrote:
 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

1) Functionality. You loose an opportunity to iterate over elements of the container. It can be resolved by extending the IntrusiveContainerNode class to store a thisPtr as well (4 more bytes per instance): // I don't want to have additional memory allocations so it is a struct now struct IntrusiveContainerNode(T) { alias T ValueType; package T next; package T prev; package T thisPtr; } and adding initialization code: class MyClass { this() { eventOne.thisPtr = this; eventTwo.thisPtr = this; } IntrusiveContainerNode!(MyClass) eventOne, eventTwo; // ... }

One technique that's worked well for me is to put the link-list controller in free functions (or a helper class). The link list looks like this: struct ContainerNode(T) { T* next; T* prev; } Then the helper has functions like this (note I'm converting from a more complex C++ so I haven't tested this). class List(T, alias listName) { T* root; Owner find(...) //Note: this could be a free function if your looking for something more light weight. { T* node = root; while(node.listName) { node = node.listName.Next; ... } } void Add(T* node) { ... } } //Use class MyClass { ContainerNode(MyClass) eventOne, eventTwo; } List!(MyClass, eventOne) eventList1; List!(MyClass, eventTwo) eventList2; MyClass c; eventList1.add(c); Another way that I've used is bolt-in templates, although I much prefer the component form as that way you get all the advantages that components bring to the table. -Joel
Aug 19 2008
prev sibling parent "Chris R. Miller" <lordSaurontheGreat gmail.com> writes:
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable

Denis Koroskin wrote:
 I use MI often and have positive experience with it. One good pattern=20
 that I use is the Intrusive container.
 Suppose you have an item that you want to store in a list.=20
 Unfortunately, putting stuff into the single- or double-linked list=20
 leads to a memory allocation (unless some pool is used). Sometimes it i=

 desirable to put next and prev elements into the item itself, so that n=

 memory allocation is ever needed. Besides, now you can easily say=20
 whether an item is stored in any container. This can be implemented via=

 inheritance:
=20
 class IntrusiveContainerNode(T)
 {
     alias T ValueType;
     package T next;
     package T prev;
 }
=20
 class IntrusiveContainer(TNode)
 {
     alias TNode.ValueType ValueType;
=20
     void add(ValueType value);
     void remove(ValueType value);
 }
=20
 class MyClass : public Node!(MyClass)
 {
    // ...
 }
=20
 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=20
 different containers:
=20
 typedef EventOneListener IntrusiveContainerNode;
 typedef EventTwoListener IntrusiveContainerNode;
=20
 class MyClass : EventOneListener!(MyClass), EventTwoListener!(MyClass)
 {
     // ...
 }
=20
 MyClass instance =3D new MyClass();
 eventOneListeners.add(instance);
 eventTwoListeners.add(instance);
=20
 It is currently impossible to implement this approach using mixins (due=

 to a bug I'm yet to submit).

Chris E. implemented something similar to that using mixins: http://www.dprogramming.com/list.php It works fairly well. Your example of typdefing to support multiple=20 lists is pretty cool though :^)
Aug 13 2008
prev sibling parent reply lurker <lurker lurk.com> writes:
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

Aug 13 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"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
Aug 13 2008
parent reply lurker <lurker lurk.com> writes:
Steven Schveighoffer Wrote:

 "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?

Yes it has no bearing. But since you answer I could not resist :) The question asked was different. I will quote it below. It included a question about possible technical difficulties.
 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.

The comparison is nonseqitur. He did not say anything about liking, he made an absolute statement. Let me partly quote the question and the answer. Q: "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)?" A: "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." Translated to pizza. Actually make it eggs because eggs are controversial. I saw egg whites as healthy items on the menu. The waitress said only yolks are bad because they have cholesterol. Had no idea. Q: "What is the current state of thought about eggs? I'd like to eat eggs, since it'd make some cheese a bit easier to eat. Are eggs not recommended because they are not not worth eating? Because they are evil and need to die (I don't know, some people could possibly be adamantly anti-eggs)?" A: "This is actually the reason, not the adamantly anti-eggs part, just that eggs are evil and that is well acknowledged almost everywhere. You will find good argumentation against it if you look, too." Didn't even have to change much of the answer. That answer is terrible in programming or kitchen domain. Superdan barged in and through his usual verbal abuse and disgusting curses he almost by mistake leaked useful information on objective nutritional data on egg yolks and egg whites. BTW pardon me if I post as lurker because I don't want my name to fall in his mouth.
Aug 13 2008
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"lurker" wrote
 Steven Schveighoffer Wrote:

 "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?

Yes it has no bearing. But since you answer I could not resist :) The question asked was different. I will quote it below. It included a question about possible technical difficulties.
 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.

The comparison is nonseqitur. He did not say anything about liking, he made an absolute statement. Let me partly quote the question and the answer. Q: "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)?" A: "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." Translated to pizza. Actually make it eggs because eggs are controversial. I saw egg whites as healthy items on the menu. The waitress said only yolks are bad because they have cholesterol. Had no idea. Q: "What is the current state of thought about eggs? I'd like to eat eggs, since it'd make some cheese a bit easier to eat. Are eggs not recommended because they are not not worth eating? Because they are evil and need to die (I don't know, some people could possibly be adamantly anti-eggs)?" A: "This is actually the reason, not the adamantly anti-eggs part, just that eggs are evil and that is well acknowledged almost everywhere. You will find good argumentation against it if you look, too." Didn't even have to change much of the answer. That answer is terrible in programming or kitchen domain. Superdan barged in and through his usual verbal abuse and disgusting curses he almost by mistake leaked useful information on objective nutritional data on egg yolks and egg whites. BTW pardon me if I post as lurker because I don't want my name to fall in his mouth.

Except that in the case of MI, the reasoning actually *is* because the author doesn't like it (translate, views as evil), and there is probably reasoning behind that (namely, experience with MI). The view that MI is evil does not come from just some random political cause, trying to eliminate MI from all programming languages. My whole beef with superdan's post is not with anything technical he said. I think what he says makes a lot of sense and was very interesting. The problem is the way he bashes the answerer, who is stating what he believes is the reason. In the interests of keeping this a civil forum with people not afraid to ask questions or not afraid to speak their mind without getting a barrage of mean-spirited obscenities, I think superdan needs to tone down his posts. It's not a healthy environment for productive discussion. FWIW, I have no problem with obscenities (not that I'm encouraging that, generally it doesn't get you as far in life to swear all the time), but I do have a problem with bullying. -Steve
Aug 13 2008
prev sibling parent "Chris R. Miller" <lordSaurontheGreat gmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable

lurker wrote:
 Steven Schveighoffer Wrote:
=20
 "lurker" wrote
 I hate to even think of it but on this one I am with Superdan. Don't =



 wrong I think he is the worst scar this group has. I think he has a r=



 problem with the way he treats people and I wouldn't want to be his=20
 coworker or neighbor. Most of his posts are so vile I feel like pukin=



 I read them and I blocked him a long time ago. In this thread I saw h=



 posts in quotes and I almost wish I didn't. But I have to say if he h=



 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=20
 ambiguity. Lars feel-good post only inforced that. Now my understandi=



 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=



 he missed it by neither affirming nor denying he knew about the layou=



 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.



 answer.  A simple question was asked.  Why does D not have Multiple=20
 inheritance.  A simple answer was given.  Because many people don't li=


 including the author (and me incidentally).  What more explaining is=20
 necessary from someone who has observed this?

Yes it has no bearing. But since you answer I could not resist :) The q=

n about possible technical difficulties.
=20
 It's like if I said to Lars "I don't like pizza" (which I actually lov=


 that's beside the point).  And Chris asks a group of people, "why does=


 Steve eat pizza?  Is it because he doesn't like it?", and Lars says "Y=


 because he doesn't like it.  Many people don't like it", and you cry f=


 and tell him off and he should not answer questions unless he *knows* =


 details.

The comparison is nonseqitur. He did not say anything about liking, he =

er.=20
=20
 Q: "What is the current state of thought about Multiple Inheritance for=

I want to do a bit easier. Is it not there because it's not worth the e= ffort to implement? Because it's evil and needs to die (I don't know, so= me people could possibly be adamantly anti-MI)?"
=20
 A: "This is actually the reason, not the adamantly anti-MI part, just t=

 evil and that is well acknowledged almost everywhere. You will find goo=

=20
 Translated to pizza. Actually make it eggs because eggs are controversi=

yolks are bad because they have cholesterol. Had no idea.
=20
 Q: "What is the current state of thought about eggs?  I'd like to eat e=

mended because they are not not worth eating? Because they are evil and n= eed to die (I don't know, some people could possibly be adamantly anti-eg= gs)?"
=20
 A: "This is actually the reason, not the adamantly anti-eggs part, just=

 evil and that is well acknowledged almost everywhere. You will find goo=

=20
 Didn't even have to change much of the answer. That answer is terrible =

l verbal abuse and disgusting curses he almost by mistake leaked useful i= nformation on objective nutritional data on egg yolks and egg whites. BTW= pardon me if I post as lurker because I don't want my name to fall in hi= s mouth. Did I already voice a fear about a zillion-post-long study of the=20 potential for ambiguity in written English? Or was that something I was = going to post and decided against it?
Aug 13 2008
prev sibling parent "Manfred_Nowak" <svv1999 hotmail.com> writes:
superdan wrote:

 no idea why walt chose to disallow that.

It may cause some problems: interface Customer { string ssn(); string name(); string uniqueName() { return name ~ "(ssn: " ~ ssn ~ ")"; } } interface SpecialCustomer { string ssn(); string name(); string uniqueName() { return name ~ "!!!!!(ssn: " ~ ssn ~ ")"; } } class D: Costumer, SpecialCostumer{ string ssn="", name="";} 1) What is the result of `(new D).uniqueName' ? 2) Is the locality of code controlable? 3) ... -manfred -- Maybe some knowledge of some types of disagreeing and their relation can turn out to be useful: http://blog.createdebate.com/2008/04/07/writing-strong-arguments/
Aug 14 2008
prev sibling next sibling parent reply "Chris R. Miller" <lordSaurontheGreat gmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable

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 stu=


 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)? =20

This is actually the reason, not the adamantly anti-MI part, just that =

 evil and that is well acknowledged almost everywhere. You will find goo=

 argumentation against it if you look, too.

Looking at superdan's message, gee whiz, that didn't take long to find=20 the implementational reasons against it. Reading about next-gen compilers like LLVM it makes me wonder with all=20 that run-time type inferencing gizmo gadgetry available at virtually no=20 cost, will this make MI (for those who want it) more feasible to=20 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=20 stack is built with LLVM for speed. There might be something to it.
 I don't know.  I know=20
 I can add a lot with mixins, but I'd just like to know what the state =


 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 =


 Objective-C programmer...  ;-)

In the languages where MI is possible, it usually also is possible to n=

 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=

 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.
 So please don't take offense, since none is meant, I just wanted to kn=


 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=20 bits and pieces seem like it would be better if they could inherit=20 behavior and data, not just a contract. It could be done through a=20 mixin, but that defeats the polymorphism I want present in the design.=20 And a Mixin and an interface just seems clunky. What if I do the mixin=20 but forget the interface, or vice-versa? Yuk! Though it would give me=20 the option of re-implementing it differently if necessary... a curious=20 silver lining.
Aug 12 2008
next sibling parent reply superdan <super dan.org> writes:
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 :)
 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).
 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.
 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.
Aug 12 2008
parent reply "Chris R. Miller" <lordSaurontheGreat gmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable

superdan wrote:
 Chris R. Miller Wrote:
=20
 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 s=




 I want to do a bit easier.  Is it not there because it's not worth t=




 effort to implement?  Because it's evil and needs to die (I don't kn=




 some people could possibly be adamantly anti-MI)? =20




 evil and that is well acknowledged almost everywhere. You will find g=



 argumentation against it if you look, too.



 the implementational reasons against it.

the sinner tells the truth dood. it's not the implementation reasons. i=

) 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 pr= ice. this "it's evil" bullshit comes from c++ people tryin' it in wrong w= ays. just like java 1 zealots yelled all over that generics are crap. the= n java 5 added (assfucked) generics. guess what. javaots changed their st= ance. sorry about the argument by comparison fallacy :) That's humorous coming from you, seeing as how you tauted nothing but=20 implementation reasons. I know a lot of Java "zealots," and they were never anti-template. The=20 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 n=


 cost, will this make MI (for those who want it) more feasible to=20
 implement?  Hmm, a curious possibility to consider.  LLVM is supposed =


 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 perpetu=

mart has nothing to do with basic graph topology. the problem definition = makes a solution impossible. this will be broken when someone invents som= e associative memory shit or some fundamental breakthrough. or when the c= ost of malloc and indirection becomes small enough to be affordable (solu= tion through tradeoff inversion). Perpetual motion is slightly different than a new and experimental=20 approach to a compiler.
 I don't know.  I know=20
 I can add a lot with mixins, but I'd just like to know what the stat=




 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 class=




 and they were sort of put off by it's lack of it.  Then again, he wa=




 Objective-C programmer...  ;-)




 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, a=



 will find it is banned in many projects for languages allowing it (li=



 C++).

I see your point though.

i don't. he has none. he keeps on saying it's a "very bad idea". he cou=

You continue to amuse me. First I say I see his point. You say you=20 don't. You say he has no point. Therefore you're absolutely certain=20 that even though someone else sees his concept that it is either false=20 or not there, or both.
 So please don't take offense, since none is meant, I just wanted to =




 what I could hope for in the future.




 bits and pieces seem like it would be better if they could inherit=20
 behavior and data, not just a contract.  It could be done through a=20
 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 mixi=


 but forget the interface, or vice-versa?  Yuk!  Though it would give m=


 the option of re-implementing it differently if necessary...  a curiou=


 silver lining.

the silver lining is in introspection. with it you can define classes t=

enough for many uses. I don't see how that would restore polymorphism. Short code example,=20 perhaps?
Aug 12 2008
parent reply Dee Girl <deegirl noreply.com> writes:
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)?  

evil and that is well acknowledged almost everywhere. You will find good argumentation against it if you look, too.

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...  ;-)

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++).

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.


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() {} } 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
Aug 12 2008
next sibling parent reply superdan <super dan.org> writes:
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)?  

evil and that is well acknowledged almost everywhere. You will find good argumentation against it if you look, too.

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...  ;-)

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++).

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.


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.
Aug 13 2008
parent Dee Girl <deegirl noreply.com> writes:
superdan Wrote:

 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.

You are right. I think, you found bug in my code! Do not tell any body ^_^ Thank you, Dee Girl
Aug 13 2008
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Dee Girl wrote:
 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).

I think it would be most helpful if you could turn this posting into an article.
Aug 13 2008
parent reply Dee Girl <deegirl noreply.com> writes:
Walter Bright Wrote:

 Dee Girl wrote:
 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).

I think it would be most helpful if you could turn this posting into an article.

Hello Walter! Thank you very much for your attention. But my English is bad. And takes me a long time to write post. So an article should take a very long time! ^_^ But if you or some body want to write an article, I help. Thank you, Dee Girl
Aug 13 2008
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Dee Girl wrote:
 Walter Bright Wrote:
 
 Dee Girl wrote:
 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).

into an article.

Hello Walter! Thank you very much for your attention. But my English is bad. And takes me a long time to write post. So an article should take a very long time! ^_^ But if you or some body want to write an article, I help. Thank you, Dee Girl

Your english is plenty good enough, and besides, there are a lot of people who'd be willing to help you with editing the grammar. But the tech ideas are yours and you should get the credit by writing about it. You've already done the hard work :-)
Aug 13 2008
parent Dee Girl <deegirl noreply.com> writes:
Walter Bright Wrote:

 Dee Girl wrote:
 Walter Bright Wrote:
 
 Dee Girl wrote:
 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).

into an article.

Hello Walter! Thank you very much for your attention. But my English is bad. And takes me a long time to write post. So an article should take a very long time! ^_^ But if you or some body want to write an article, I help. Thank you, Dee Girl

Your english is plenty good enough, and besides, there are a lot of people who'd be willing to help you with editing the grammar. But the tech ideas are yours and you should get the credit by writing about it. You've already done the hard work :-)

I email Andrei. He said he can help me! But he said he has same idea earlier ^_^. I think he is right. The idea is standard. He also said a introspection does not work now. You and him can discuss. Thank you both very much for every thing, Dee Girl
Aug 13 2008
prev sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Dee Girl a écrit :
...

I really like the way you write English, in short sentences which are 
very clear. Were you from Japan? I can't remember. Are you thinking in 
japanese and translating to English? Is japanese spoken like that? Or is 
it just you?

I would have sent this mail to you privately, but you don't show your 
email here.

(sorry, I like languages)
Aug 13 2008
parent reply Dee Girl <deegirl noreply.com> writes:
Ary Borenszweig Wrote:

 Dee Girl a écrit :
 ...
 
 I really like the way you write English, in short sentences which are 
 very clear. Were you from Japan? I can't remember. Are you thinking in 
 japanese and translating to English? Is japanese spoken like that? Or is 
 it just you?
 
 I would have sent this mail to you privately, but you don't show your 
 email here.
 
 (sorry, I like languages)

Hello Ary! Thank you for asking. I was raised in Tokyo. Now I am a student in USA. Very different! Home teacher tells you what to do. Here teacher lets you very free. I can take what class I want. Some time I work on any project I want and get good grade to. In Japan I would be ashamed. America is very free country. Best for programmers I think ^_^ I write longer sentences in Japanese. I try to keep short in English and put one sense in a sentence. I never know where to put comma and articles are all in strange places. So I apply KISS ^_^ Thank you, Dee Girl
Aug 13 2008
next sibling parent BCS <ao pathlink.com> writes:
Reply to Dee,

 Ary Borenszweig Wrote:
 
 Dee Girl a écrit :
 ...
 I really like the way you write English, in short sentences which are
 very clear. Were you from Japan? I can't remember. Are you thinking
 in japanese and translating to English? Is japanese spoken like that?
 Or is it just you?
 
 I would have sent this mail to you privately, but you don't show your
 email here.
 
 (sorry, I like languages)
 

student in USA. Very different! Home teacher tells you what to do. Here teacher lets you very free. I can take what class I want. Some time I work on any project I want and get good grade to. In Japan I would be ashamed. America is very free country. Best for programmers I think ^_^ I write longer sentences in Japanese. I try to keep short in English and put one sense in a sentence. I never know where to put comma and articles are all in strange places. So I apply KISS ^_^ Thank you, Dee Girl

Sometimes I wish more people (my self included) did that. One mark of an expert in a language is someone who can say something that takes you 10 minuets to figure out is even correct and another 10 minutes to understand. A better grasp of a language does /not/ automatically make you easier to understand. <g> http://www.ioccc.org/
Aug 13 2008
prev sibling parent "Chris R. Miller" <lordSaurontheGreat gmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable

Dee Girl wrote:
 Ary Borenszweig Wrote:
=20
 Dee Girl a =E9crit :
 ...

 I really like the way you write English, in short sentences which are =


 very clear. Were you from Japan? I can't remember. Are you thinking in=


 japanese and translating to English? Is japanese spoken like that? Or =


 it just you?

 I would have sent this mail to you privately, but you don't show your =


 email here.

 (sorry, I like languages)

Hello Ary! Thank you for asking. I was raised in Tokyo. Now I am a stud=

er lets you very free. I can take what class I want. Some time I work on = any project I want and get good grade to. In Japan I would be ashamed. Am= erica is very free country. Best for programmers I think ^_^
=20
 I write longer sentences in Japanese. I try to keep short in English an=

es are all in strange places. So I apply KISS ^_^ Thank you, Dee Girl I end up working with a lot of ESL people, and I wish more of them had=20 your wisdom to keep their English within levels of complexity they are=20 comfortable with. True, there are a few grammar errors ever here and=20 there in your text. In the long run it's still readable and you can=20 still understand what you're saying (which is different from what is=20 said due to the brain's ability to heuristically imply meaning).
Aug 13 2008
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Chris R. Miller wrote:
 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.

If you forget the mixin, you'll get a compile error about unimplemented methods. If you forget the interface, you'll get a compile error about illegal implicit casts.
Aug 13 2008
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
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  



 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


 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

 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  

 that or just use the default. no idea why walt chose to disallow  

 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).
Aug 13 2008
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Wed, 13 Aug 2008 20:52:24 +0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 "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



 classes in D?  I'd like to have that feature, since it'd make  



 stuff
 I want to do a bit easier.  Is it not there because it's not  



 the
 effort to implement?  Because it's evil and needs to die (I  



 know,
 some people could possibly be adamantly anti-MI)?

This is actually the reason, not the adamantly anti-MI part, just


 MI
 is
 evil and that is well acknowledged almost everywhere. You will  


 good
 argumentation against it if you look, too.

appeal to authority. appeal to ridicule. appeal to the majority.

in
 one sentence. wow. at least could you space out your fallacies a  

 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

 that or just use the default. no idea why walt chose to disallow

 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

1) Functionality. You loose an opportunity to iterate over elements of the container. It can be resolved by extending the IntrusiveContainerNode class to store a thisPtr as well (4 more bytes per instance): // I don't want to have additional memory allocations so it is a struct now struct IntrusiveContainerNode(T) { alias T ValueType; package T next; package T prev; package T thisPtr; } and adding initialization code: class MyClass { this() { eventOne.thisPtr = this; eventTwo.thisPtr = this; } IntrusiveContainerNode!(MyClass) eventOne, eventTwo; // ... } 2) Readability. In addition to the complexity above, you are now forced to write the following code instead: eventOneListeners.add(&instance.eventOne); eventTwoListeners.add(&instance.eventTwo); 3) Usability. You have to remember all the names like "eventOne", "eventTwo" or whatever name you give to the node. In some cases users are forced to stick with some predefined names, code becomes templated and losses virtuality. The following code shows the issues: class UpdateDispatcher { void addEventListener(T)(T listener) // a template. non-virtual. { updateContainer.add(listener.updateEvent); // updateEvent is a predefined name. //All the classes that want to recieve an Update should have a public "updateEvent" field in their body! } } 4) Performance. Additional pointer dereference (node->thisPtr->data) introduced (minor one, but nevertheless). All these issues make the idiom unusable.
Aug 13 2008
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Wed, 13 Aug 2008 22:02:14 +0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 "lurker" wrote
 Steven Schveighoffer Wrote:

 "lurker" wrote
I hate to even think of it but on this one I am with Superdan. Don't  

me
wrong I think he is the worst scar this group has. I think he has a  

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  

posts in quotes and I almost wish I didn't. But I have to say if he  

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  

 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  

 But
 he missed it by neither affirming nor denying he knew about the  

 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?

Yes it has no bearing. But since you answer I could not resist :) The question asked was different. I will quote it below. It included a question about possible technical difficulties.
 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.

The comparison is nonseqitur. He did not say anything about liking, he made an absolute statement. Let me partly quote the question and the answer. Q: "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)?" A: "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." Translated to pizza. Actually make it eggs because eggs are controversial. I saw egg whites as healthy items on the menu. The waitress said only yolks are bad because they have cholesterol. Had no idea. Q: "What is the current state of thought about eggs? I'd like to eat eggs, since it'd make some cheese a bit easier to eat. Are eggs not recommended because they are not not worth eating? Because they are evil and need to die (I don't know, some people could possibly be adamantly anti-eggs)?" A: "This is actually the reason, not the adamantly anti-eggs part, just that eggs are evil and that is well acknowledged almost everywhere. You will find good argumentation against it if you look, too." Didn't even have to change much of the answer. That answer is terrible in programming or kitchen domain. Superdan barged in and through his usual verbal abuse and disgusting curses he almost by mistake leaked useful information on objective nutritional data on egg yolks and egg whites. BTW pardon me if I post as lurker because I don't want my name to fall in his mouth.

Except that in the case of MI, the reasoning actually *is* because the author doesn't like it (translate, views as evil), and there is probably reasoning behind that (namely, experience with MI). The view that MI is evil does not come from just some random political cause, trying to eliminate MI from all programming languages. My whole beef with superdan's post is not with anything technical he said. I think what he says makes a lot of sense and was very interesting. The problem is the way he bashes the answerer, who is stating what he believes is the reason. In the interests of keeping this a civil forum with people not afraid to ask questions or not afraid to speak their mind without getting a barrage of mean-spirited obscenities, I think superdan needs to tone down his posts. It's not a healthy environment for productive discussion. FWIW, I have no problem with obscenities (not that I'm encouraging that, generally it doesn't get you as far in life to swear all the time), but I do have a problem with bullying. -Steve

Please, stop that!
Aug 13 2008
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Thu, 14 Aug 2008 02:50:00 +0400, Chris R. Miller  
<lordSaurontheGreat gmail.com> wrote:

 Denis Koroskin wrote:
 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).

Chris E. implemented something similar to that using mixins: http://www.dprogramming.com/list.php It works fairly well. Your example of typdefing to support multiple lists is pretty cool though :^)

Well, yes, it uses the same idea, but implementation is different. It has a few problems, though: an item is limited to a single container (I can do the same with single inheritance) and is a list itself (although it is useful in some cases, it is undesired in general). I'll post my implementation with mixins soon (today, hopefully).
Aug 14 2008
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Thu, 14 Aug 2008 16:09:57 +0400, Manfred_Nowak <svv1999 hotmail.com>  
wrote:

 superdan wrote:

 no idea why walt chose to disallow that.

It may cause some problems: interface Customer { string ssn(); string name(); string uniqueName() { return name ~ "(ssn: " ~ ssn ~ ")"; } } interface SpecialCustomer { string ssn(); string name(); string uniqueName() { return name ~ "!!!!!(ssn: " ~ ssn ~ ")"; } } class D: Costumer, SpecialCostumer{ string ssn="", name="";} 1) What is the result of `(new D).uniqueName' ? 2) Is the locality of code controlable? 3) ... -manfred

I think the class should become abstract unless it reimplements the uniqueName(), ssn() and name() methods. Problem is, ssn and name variables are in a conflicting state with the methods of the same name. class D : class D: Costumer, SpecialCostumer { string ssn="", name=""; } class E : D { string ssn() { return super.ssn; } string name() { return super.name; } string uniqueName() { return Costumer.uniqueName() } }
Aug 14 2008
prev sibling next sibling parent Sclytrack <sclytrack pi.be> writes:
D will never support Multiple Inheritance.
It is evil and must die (from the options you gave me).
Also it is easier to memorize a tree structure than a spider web.
Well you already know the workarounds.

/me needs to use more structs over classes. They're a heck of a lot faster.
Aug 12 2008
prev sibling next sibling parent Wyverex <wyverex.cypher gmail.com> writes:
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...
Aug 13 2008
prev sibling next sibling parent reply BLS <nanali nospam-wanadoo.fr> writes:
I guess D will never support MI.
Beside Mixins and Interfaces, you have the option to implement the (not 
very well known) twin pattern to simulate multiple inheritance.

Google for:
Twin – A Design Pattern for Modeling Multiple Inheritance

Page 4-6 , for the impatient.

/I don't use this pattern 'cause it produces too much overhead, and it 
does't solve all the problems  /

Bjoern
ps
I do not belong to the "MI is eval" group. ... probabely more to the "MI 
in C++ is eval folks".
I think  Eiffel shows that at lesat some MI related problems can be solved.
Aug 14 2008
parent reply "Chris R. Miller" <lordSaurontheGreat gmail.com> writes:
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

BLS wrote:
 I guess D will never support MI.
 Beside Mixins and Interfaces, you have the option to implement the (not=

 very well known) twin pattern to simulate multiple inheritance.
=20
 Google for:
 Twin =96 A Design Pattern for Modeling Multiple Inheritance
=20
 Page 4-6 , for the impatient.
=20
 /I don't use this pattern 'cause it produces too much overhead, and it
 does't solve all the problems  /
=20
 Bjoern
 ps
 I do not belong to the "MI is eval" group. ... probabely more to the "M=

 in C++ is eval folks".
 I think  Eiffel shows that at lesat some MI related problems can be sol=

I don't think it's evil, but I acknowledge that a sufficiently advanced idiot can abuse it to the point of making a code base un-salvageable. Then again, there are a ton of useful tools that can be quite entertaining in the hands of a sufficiently curious idiot ("what's this nailgun do?")
Aug 14 2008
parent BLS <nanali nospam-wanadoo.fr> writes:
Chris R. Miller schrieb:
 BLS wrote:
 I guess D will never support MI.
 Beside Mixins and Interfaces, you have the option to implement the (not
 very well known) twin pattern to simulate multiple inheritance.

 Google for:
 Twin – A Design Pattern for Modeling Multiple Inheritance

 Page 4-6 , for the impatient.

 /I don't use this pattern 'cause it produces too much overhead, and it
 does't solve all the problems  /

 Bjoern
 ps
 I do not belong to the "MI is eval" group. ... probabely more to the "MI
 in C++ is eval folks".
 I think  Eiffel shows that at lesat some MI related problems can be solved.

I don't think it's evil, but I acknowledge that a sufficiently advanced idiot can abuse it to the point of making a code base un-salvageable. Then again, there are a ton of useful tools that can be quite entertaining in the hands of a sufficiently curious idiot ("what's this nailgun do?")

see what happens...) Bjoern
Aug 14 2008
prev sibling next sibling parent JAnderson <ask me.com> writes:
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)?  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...  ;-)
 
 So please don't take offense, since none is meant, I just wanted to know 
 what I could hope for in the future.
 

I don't think MI is evil however I think there's only a few places where it's actually a good design choice. I think inheritance should mainly be used for polymorphism and not "reuse" (see : 101 Rules, Guidelines, and Best Practices (C++ In-Depth Series) -> by Herb Sutter and Andrei Alexandrescu). By reuse of course I mean inheriting from a class that has partial implementation. - Components provide better encapsulation because you have to go though the components interface to get at anything, which means you can provide a very strong invariant shield. - Components can be many. That is say you had a uni-cycle and you wanted to add more wheels. You can with components. - Components are not so tightly coupled. You can (many times) remove the component without changing the interface. You can also make changes to the components interface and have a very small ripple effect across the project. - Components can provide there own interface and can be bound at runtime. This means you can switch out the component as needed. - Components can be passed around without dragging the entire class along for the ride. - Not in the design area but... some companies working on consoles use components to get around v-table issues. (Note I've only mentioned a few of the advantages of components.) Anyway given that most of the time IMHO you shouldn't be using inheritance for implementation details / data. Add to that mixins and bolt-in templates and it becomes even less likely that multiple inheritance with implementation is the best design for your application. I think D has taken the right approach, which is to make it hard to write error-prone code. -Joel
Aug 14 2008
prev sibling parent reply The User <the-user gradespro.com> writes:
Java allows only a few concepts and design-patterns like MVC or Delegation and
polymorphism. But there is not one correct and one wrong design-pattern. D
tried to accept more concepts like templates and mixins, you could also accept
MI.
Policy-based Design (http://en.wikipedia.org/Policy-Based_Design) is a very
powerful, modern and flexible design-pattern wich makes usage of MI.
STL and Boost use MI and are excellent designed.
Features cannot be evil, but they can be used in a wrong way. MI would allow
more flexibility, sometimes more elegant code and more design-patterns.
D is not a prototype anymore, now it could add new features, 
http://www.pmg.lcs.mit.edu/papers/bidirectional.pdf shows us, how it could work.

The User
Dec 26 2008
next sibling parent Yigal Chripun <yigal100 gmail.com> writes:
The User wrote:
 Java allows only a few concepts and design-patterns like MVC or Delegation and
polymorphism. But there is not one correct and one wrong design-pattern. D
tried to accept more concepts like templates and mixins, you could also accept
MI.
 Policy-based Design (http://en.wikipedia.org/Policy-Based_Design) is a very
powerful, modern and flexible design-pattern wich makes usage of MI.
 STL and Boost use MI and are excellent designed.
 Features cannot be evil, but they can be used in a wrong way. MI would allow
more flexibility, sometimes more elegant code and more design-patterns.
 D is not a prototype anymore, now it could add new features, 
http://www.pmg.lcs.mit.edu/papers/bidirectional.pdf shows us, how it could work.

 The User

MI is in fact evil. especially the C++ kind. there are two concepts conflated here - subtyping and subclassing. They shouldn't be connected but they in fact are. MI aggravates this a thousand fold. the first is subtyping: you want to model your objects such that they'll be subtypes of two different types, for example. Java/C#/D easy solution: interface A {..} interface B {..} interface/class ident : A, B {..} you want to subclass two types (i.e copy the implementation) Easy in D: template A {..} template B {..} class ident { mixin A; mixin B; ..} you want to do both (which is what C++ MI does): class ident : A, B { mixin impl_A; mixin impl_B; ... } here, D supports MI. without all the problems in C++ C++ style MI is EVIL exactly because it conflate two separate concepts into one. If you explore C++ use of MI you'll see that 95% of cases it is used to do the subtyping (interfaces). and doing subclassing with it is very rare and usually discouraged due to complexity.
Dec 26 2008
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
The User:

This is the wikipedia page you refer to:
http://en.wikipedia.org/wiki/Policy-based_design

The signal in that C++ code is almost lost in syntactic noise.
This is a D version, I hope the original meaning isn't lost:

import std.stdio: writefln;

struct HelloLanguagePolicyEnglish {
    static string message() {
        return "Hello, World!";
    }
}

struct HelloLanguagePolicyGerman {
    static string message() {
        return "Hallo Welt!";
    }
}

struct HelloOutputPolicy {
    static void print(T)(T message) {
        writefln(message);
    }
}

struct Hello(OutputPolicy, LanguagePolicy) {
    // behaviour method
    static public void run() {
        // two policy methods
        OutputPolicy.print(LanguagePolicy.message());
    }
}

void main() {
    // prints Hello World!
    Hello!(HelloOutputPolicy, HelloLanguagePolicyEnglish).run;

    // does the same but uses another policy, the language has changed
    // prints Hallo Welt!
    Hello!(HelloOutputPolicy, HelloLanguagePolicyGerman).run;
}


An alternative D version:

import std.stdio: writefln;

template HelloLanguagePolicyEnglish() {
    string message() {
        return "Hello, World!";
    }
}

template HelloLanguagePolicyGerman() {
    string message() {
        return "Hallo Welt!";
    }
}

template HelloOutputPolicy() {
    void print(T)(T message) {
        writefln(message);
    }
}

struct Hello(alias OutputPolicy, alias LanguagePolicy) {
    // behaviour method
    static void run() {
        // two policy methods
        OutputPolicy!().print(LanguagePolicy!().message());
    }
}

void main() {
    // prints Hello World!
    Hello!(HelloOutputPolicy, HelloLanguagePolicyEnglish).run;

    // does the same but uses another policy, the language has changed
    // prints Hallo Welt!
    Hello!(HelloOutputPolicy, HelloLanguagePolicyGerman).run;
}

Bye,
bearophile
Dec 26 2008
prev sibling parent Don <nospam nospam.com> writes:
The User wrote:
 Java allows only a few concepts and design-patterns like MVC or Delegation and
polymorphism. But there is not one correct and one wrong design-pattern. D
tried to accept more concepts like templates and mixins, you could also accept
MI.
 Policy-based Design (http://en.wikipedia.org/Policy-Based_Design) is a very
powerful, modern and flexible design-pattern wich makes usage of MI.
 STL and Boost use MI and are excellent designed.
 Features cannot be evil, but they can be used in a wrong way. MI would allow
more flexibility, sometimes more elegant code and more design-patterns.
 D is not a prototype anymore, now it could add new features, 
http://www.pmg.lcs.mit.edu/papers/bidirectional.pdf shows us, how it could work.
 
 The User

Andrei invented Policy-based design, and he's one of the key designers of D. So don't worry about D missing out on functionality in that area <g>.
Dec 27 2008