December 02, 2006
On 12/02/2006 09:27 AM, Burton Radons wrote:
[snip]
> I don't have a perfect solution to the problem; there is none because it's asking two objects to exist in one space and we need to resolve that. But given that multiple inheritance is sometimes necessary, waving it off as "too complex" or "bad form" is impractical; like any type of suppression, that only leads to cracking and nasty leaks (mixins).
> 
> I have an idea. Let's try making this assertion: no type will have in its inheritance tree another type multiple times without being an abuse of multiple inheritance. Given this statement, can anyone find an 
[snip]
> Yeah, but C++ programmers are programming in C++. The hell do they know about good language practices? ;-)

How would the D equivalent to mpl::inherit_linearly<, inherit<,>, >
(see http://www.boost.org/libs/mpl/doc/refmanual/inherit-linearly.html)
work without using the MI class, inherit?
December 03, 2006
Larry Evans wrote:
> On 12/02/2006 09:27 AM, Burton Radons wrote:
> [snip]
>> I don't have a perfect solution to the problem; there is none because it's asking two objects to exist in one space and we need to resolve that. But given that multiple inheritance is sometimes necessary, waving it off as "too complex" or "bad form" is impractical; like any type of suppression, that only leads to cracking and nasty leaks (mixins).
>>
>> I have an idea. Let's try making this assertion: no type will have in its inheritance tree another type multiple times without being an abuse of multiple inheritance. Given this statement, can anyone find an 
> [snip]
>> Yeah, but C++ programmers are programming in C++. The hell do they know about good language practices? ;-)
> 
> How would the D equivalent to mpl::inherit_linearly<, inherit<,>, >
> (see http://www.boost.org/libs/mpl/doc/refmanual/inherit-linearly.html)
> work without using the MI class, inherit?

God, Boost makes me want to stab my eyes out.
December 03, 2006
Larry Evans wrote:
> How would the D equivalent to mpl::inherit_linearly<, inherit<,>, >
> (see http://www.boost.org/libs/mpl/doc/refmanual/inherit-linearly.html)
> work without using the MI class, inherit?

I would suggest using instead D's ability to declare the members of a struct using tuples.
December 03, 2006
Larry Evans wrote:
> On 12/02/2006 09:27 AM, Burton Radons wrote:
> [snip]
>> I don't have a perfect solution to the problem; there is none because it's asking two objects to exist in one space and we need to resolve that. But given that multiple inheritance is sometimes necessary, waving it off as "too complex" or "bad form" is impractical; like any type of suppression, that only leads to cracking and nasty leaks (mixins).
>>
>> I have an idea. Let's try making this assertion: no type will have in its inheritance tree another type multiple times without being an abuse of multiple inheritance. Given this statement, can anyone find an 
> [snip]
>> Yeah, but C++ programmers are programming in C++. The hell do they know about good language practices? ;-)
> 
> How would the D equivalent to mpl::inherit_linearly<, inherit<,>, >
> (see http://www.boost.org/libs/mpl/doc/refmanual/inherit-linearly.html)
> work without using the MI class, inherit?

That's a good example. Here's another from Wikipedia:

    Animal
    Mammal : Animal
    Winged : Animal
    Bat : Mammal, Winged

Contrived but not unreasonable, but I think the problem I gave applies even if they don't override any of the parent methods, just as a pure maintainer problem of the subclasses depending upon the implementation of the parent class.

We could restrict diamonds to interfaces, like it's done now, but that feels like a hack and doesn't actually solve the problem - in fact, it makes the problem necessary. Damn. I retract my challenge.

Perhaps we're trying to shoehorn two types of inheritance into one tree. Something that's Winged is an Animal, but it's not a /complete/ animal; it's not going to have any opinion on its feeding habits. So we could use:

    Animal
    Mammal : Animal
    Winged : abstract Animal
    Bat : Mammal, Winged

And allow the diamond because Winged can't override anything from Animal. This is bad because Animal might have stuff Winged has an opinion on, but more discrete selections of inheritance (which are a good idea anyway) allows us to defeat the diamond when we need to:

    Reproduction
    Movement
    Animal : Reproduction, Movement
    Mammal : abstract Animal, Reproduction
    Winged : abstract Animal, Movement
    Bat : Mammal, Winged

In this case Mammal and Winged are exclusive, so the tree works properly.

I'd analyse your example more but I'm unfamiliar with Boost. Can you factor the problem so that it can be expressed in terms of animals? :-)
December 04, 2006
On 12/02/2006 10:11 PM, Burton Radons wrote:
> Larry Evans wrote:
> 
>> On 12/02/2006 09:27 AM, Burton Radons wrote:
[snip]
> And allow the diamond because Winged can't override anything from Animal. This is bad because Animal might have stuff Winged has an opinion on, but more discrete selections of inheritance (which are a good idea anyway) allows us to defeat the diamond when we need to:
> 
>     Reproduction
>     Movement
>     Animal : Reproduction, Movement
>     Mammal : abstract Animal, Reproduction
>     Winged : abstract Animal, Movement
>     Bat : Mammal, Winged
> 
> In this case Mammal and Winged are exclusive, so the tree works properly.
> 
> I'd analyse your example more but I'm unfamiliar with Boost. Can you factor the problem so that it can be expressed in terms of animals? :-)

Well, I'm kinda agreeing with Walter.  AFAICT, the example in
boost which used inherit was used to create a tuple, and since
there's now a better way (as Walter pointed-out), I'm reluctant
to try.  However, if I did, there would be a problem with the
abstract Animal (or virtual Animal in c++ case).  I don't
see a way that can be done with c++ metaprogramming since
all the args to boost::mpl::inherit have to be types, and, AFAICT,
there's no type, virtual X, for any type X, in c++.

December 10, 2006
On 12/02/2006 09:33 PM, Walter Bright wrote:
> Larry Evans wrote:
> 
>> How would the D equivalent to mpl::inherit_linearly<, inherit<,>, >
>> (see http://www.boost.org/libs/mpl/doc/refmanual/inherit-linearly.html)
>> work without using the MI class, inherit?
> 
> 
> I would suggest using instead D's ability to declare the members of a struct using tuples.
Good point.

Now, I've another use of c++ MI, and I'm wondering how to do the
equivalent in D.  This use involves "dynamic inheritance" which is
somewhat like the 12.7 Delegation in Stroustrup's _Design and Evolution
of c++_.  The code is used here:

  http://preview.tinyurl.com/wwsee

The test code is in the corresponding libs/grammar_pipeline/test
directory.  One application of such dynamic inheritance was discussed
here:

  http://article.gmane.org/gmane.comp.lib.boost.devel/99421

Of course, a more concrete application was in the aforementioned
tinurl reference.

So...how would this be done in D?  Since the above application involved calculating grammar lookahead sets, and since you're interested in
emulating spirit in D, this might provide some further motivation
for finding a D equivalent :)
December 13, 2006
Larry Evans wrote:
> So...how would this be done in D?  Since the above application involved calculating grammar lookahead sets, and since you're interested in
> emulating spirit in D, this might provide some further motivation
> for finding a D equivalent :)

Could you provide a distilled explanation of what dynamic inheritance is?
December 21, 2006
On 12/12/2006 09:49 PM, Walter Bright wrote:
> Larry Evans wrote:
>
>> So...how would this be done in D?  Since the above application
>> involved calculating grammar lookahead sets, and since you're
>> interested in
>> emulating spirit in D, this might provide some further motivation
>> for finding a D equivalent :)
>
>
> Could you provide a distilled explanation of what dynamic inheritance is?

:* Distilled_Explanation:

Dynamic Inheritance (a.k.a. DI, as coded here:

in http://tinyurl.com/yd7ean

) is really nothing more than the
"infrastructure" for implementing "Dynamic Dual Heirarchies" as
described on p. 5 of:

http://www.objectmentor.com/resources/articles/dih.pdf

which says:

  A dual heirarchy is like a ladder. The two inheritance heirarchies
  are the supports of the ladder, and in the INTELLIGENT CHILDREN
  pattern above, the 'has' relationships in the peers are the rungs of
  the ladder.

An "abstract" picture of such a dual heirarchy is in figure 3 on p. 4.
The left side of figure 3 is closer to DI than the right side.  This
is because the 'has' relationship is stored in the base class ( DI's
dyn_inherit::inherit<,,>::super_type::my_ref, corresponding to figure
3's right-pointing solid arrow from B1 to B2).  Thus, DI's inherit<,,>
corresponds to figure 3's B1 and DI's inherit's DynSupertype template
parameter corresponds to figure 3's B2.

A more "concrete" picture is figure 2, where lhs of figure 3's B1
corresponds to figure 2's Observer, and lhs of figure 3's B2
corresponds to figure 2's Subject.  In contrast to the Observer pattern
which figure 2 describes, DI just has one pointer (as opposed to a set
of pointers) from B2 (Subject) to B1 (Observers).  This single pointer
is stored in the dyn_inherit::base::my_subtype member of the DynSupertype of
inherit (note the REQUIREMENTS: comment after DynSupertype specifying
that it's derived from dyn_inherit::base).

:* Preliminary_Conclusion

Well, Walter, after I complete the :* Distilled_Explanation below, I
realized there's probably no need for Proxy<> supertype of
dyn_inherit::inherit,
Instead this class could be made a field and the "relevant" function
calls forwarded to the Proxy<>::get_ref() as done with the current
implementation (e.g. as done by the eff::exp_tree::top::begin method here:

http://tinyurl.com/yht62d

).  However, that still leaves the dyn_inherit::base and DeltaType
supertypes of dyn_inherit::inherit. So..., how would
dyn_inherit::inherit be coded in D?

;* Name_and_Location_Rationale:

Some of the names (for example DynSuperType and  DeltaType for the 1st
and 2nd inherit template arguments) may seem mysterious. The following
explains how these names were selected.

:** DynSuperType_Rationale:

The reason for the DynSuperType (and it's inclusion in the
Proxy<DynSuperType> supertype of inherit) is that type inherit
supertype is "supposed" to correspond to the *p supertype of C in:

  class C : *p { ... };

from section 12.7, "Delegation", of Stroustrup's
_Design & Evolution of C++_.  The reason for the "supposed" qualifier
above is that there's no automatic forwarding to *p as described in
section 12.7.  Since D has delegates, I thought maybe D could do this
forwarding ( I confess, I've not written a single D program yet ).
However, after reading:

  http://www.digitalmars.com/d/type.html#delegates

I guess not, since delegates point to single functions instead of to
classes :( .

Would Mixin's be any help?.  Well,
http://www.digitalmars.com/d/mixin.html seems to say that a select set
of declarations are *copied* from one context into another; however,
what I want needed is delegation to each of the selected functions in
the source context (i.e. the SynSuperType).  Hence, I guess mixins
wouldn't help either :(

:** DeltaType_Rationale:

The Delta comes from p. 2 of _Mixin-based Inheritance_ by Braca and
Cook, which is available here:

http://citeseer.ist.psu.edu/bracha90mixinbased.html

.  This Mixin part of the title tempts me to rethink whether D's
mixin's can be some help, but, as mentioned above, I've not yet
written a D program.  I guess I should start ;) .
1 2
Next ›   Last »