August 12, 2008
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.

August 13, 2008
superdan wrote:
> Chris R. Miller Wrote:
> 
>> Lars Ivar Igesund wrote:
>>> Chris R. Miller wrote:
>>>> Understand, I'm NOT demanding ANYTHING.
>>>>
>>>> What is the current state of thought about Multiple Inheritance for classes in D?  I'd like to have that feature, since it'd make some stuff I want to do a bit easier.  Is it not there because it's not worth the effort to implement?  Because it's evil and needs to die (I don't know, some people could possibly be adamantly anti-MI)?
>>> This is actually the reason, not the adamantly anti-MI part, just that MI is evil and that is well acknowledged almost everywhere. You will find good argumentation against it if you look, too.
>> Looking at superdan's message, gee whiz, that didn't take long to find the implementational reasons against it.
> 
> the sinner tells the truth dood. it's not the implementation reasons. it's the reasons, period. there's no others. with one exception (smalltalk) all languages without fixed field layout do use mi. why? because aside from field layout there is no reason not to, and they already paid the price. this "it's evil" bullshit comes from c++ people tryin' it in wrong ways. just like java 1 zealots yelled all over that generics are crap. then java 5 added (assfucked) generics. guess what. javaots changed their stance. sorry about the argument by comparison fallacy :)

That's humorous coming from you, seeing as how you tauted nothing but implementation reasons.

I know a lot of Java "zealots," and they were never anti-template.  The zealots in your neck of the woods must be more bipolar than mine.

>> Reading about next-gen compilers like LLVM it makes me wonder with all that run-time type inferencing gizmo gadgetry available at virtually no cost, will this make MI (for those who want it) more feasible to implement?  Hmm, a curious possibility to consider.  LLVM is supposed to be wicked fast, too.  My Apple friend tells me that most of OS X's GL stack is built with LLVM for speed.  There might be something to it.
> 
> i'll make another analogy. with all that research n shit, isn't perpetual motion closer to reality now? hell no. the fact that llvm is fast or smart has nothing to do with basic graph topology. the problem definition makes a solution impossible. this will be broken when someone invents some associative memory shit or some fundamental breakthrough. or when the cost of malloc and indirection becomes small enough to be affordable (solution through tradeoff inversion).

Perpetual motion is slightly different than a new and experimental approach to a compiler.

>>>> I don't know.  I know
>>>> I can add a lot with mixins, but I'd just like to know what the state of
>>>> the feature is.
>>>>
>>>> The reason is I was trying to explain how cool D is to some other friends of mine, and they asked about Multiple Inheritance (of classes) and they were sort of put off by it's lack of it.  Then again, he was an Objective-C programmer...  ;-)
>>> In the languages where MI is possible, it usually also is possible to not shoot your own foot with some care, in which case it can appear as a powerful feature. But almost everywhere it just is a very bad idea, and you will find it is banned in many projects for languages allowing it (like C++).
>> Look long enough and you can find anything.  ;-)
>>
>> I see your point though.
> 
> i don't. he has none. he keeps on saying it's a "very bad idea". he could sing it for all i care. how does that make it more pointful.

You continue to amuse me.  First I say I see his point.  You say you don't.  You say he has no point.  Therefore you're absolutely certain that even though someone else sees his concept that it is either false or not there, or both.

>>>> So please don't take offense, since none is meant, I just wanted to know what I could hope for in the future.
>>> You should hope you can redesign your application to not need MI ;)
>> Yeah, it's trivial to work around it (I did come from Java!) but some bits and pieces seem like it would be better if they could inherit behavior and data, not just a contract.  It could be done through a mixin, but that defeats the polymorphism I want present in the design. And a Mixin and an interface just seems clunky.  What if I do the mixin but forget the interface, or vice-versa?  Yuk!  Though it would give me the option of re-implementing it differently if necessary...  a curious silver lining.
> 
> the silver lining is in introspection. with it you can define classes that define forwarding functions to other classes. that is almost mi, good enough for many uses.

I don't see how that would restore polymorphism.  Short code example, perhaps?



August 13, 2008
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 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.

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 that there's a reason he doesn't.

The moment I saw a reply by superdan my first thought was "oh god, not another zillion-message-long study in the ambiguity possible in written English."  I was mighty tempted to not read superdan's messages, but through the "colorful" language there was a few bits of substance - mainly an explanation of why it's a difficult thing to implement.



August 13, 2008
"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.


August 13, 2008
Chris R. Miller Wrote:

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

I do not know exact how he meant. But I tell how I think it can be. This is how I implement in my project (simplified because I have negative offset).

class Base1
{
    int i1;
    void f1() {}
}

class Base2
{
    int i2;
    void f2() {}
}

Goal to define Derived that inherits Base1 and Base2. Derived override both f1 and f2. And contains both i1 and i2. Also Derived implicit convert to Base1 and Base2. Very hard! But can be done. Strategy is derive from one and contain other.

class Derived : Base1
{
    override void f1() {}
    private Base2 b2;
    void f2() { return b2.f2; }
}

This is first try. I do not put constructor to simplify code. Assume b2 initialized ok. Converts to Base1 but not Base2. Let us fix:

class Derived : Base1
{
    override void f1() {}
    private Base2 b2;
    void f2() {}
    Base2 opImplicitCast() { return b2; }
}

Now converts to both. Like inheritance! But see last problem. And most complex. f2 does not override f2 in base. I did it manual but here I use inner classes because they make code simple.

class Derived : Base1
{
    override void f1() {}
    class Base2Hook : Base2
    {
        override void f2() { return outer.f2; }
    }
    private Base2Hook b2;
    void f2() {}
    Base2 opImplicitCast() { return b2; }
}

Now we have all. Derived implements both f1 and f2 and contains i1 and i2. Converts implicit to Base1 and Base2. When you call f2 on the Base2 part correct function is called. It is all good! But it is one more indirection for the Base2 part. Also there is code boring (boilerplate). With introspection it can be generated. So ideal solution is:

class Derived : Base1
{
    override void f1() {}
    mixin(innerHookForwarder("Base2Hook", "Base2"));
    private Base2Hook b2;
    Base2 opImplicitCast() { return b2; }
    void f2() {}
}

Maybe simpler:

class Derived : Base1
{
    mixin(psuedoInheritance("Base2", "b2"));
    override void f1() {}
    void f2() {}
}

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
August 13, 2008
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
August 13, 2008
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)



August 13, 2008
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.
August 13, 2008
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.
August 13, 2008
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.