September 29, 2020
On Tuesday, 29 September 2020 at 20:29:49 UTC, jmh530 wrote:
> On Tuesday, 29 September 2020 at 18:38:29 UTC, mw wrote:
>> [snip]
>>
>> Good to hear, I opened an discussion issue here:
>>
>> https://github.com/jll63/openmethods.d/issues/19
>>
>> Anyone who's interested in the implementation, let's continue the brain storming there.
>
> You might recall that back in June I wrote [1] that D does not have the ability to properly disable base members and member functions, which would make implementing Eiffel-like semantics significantly easier as part of the base language.
>
> [1] https://forum.dlang.org/post/tpwwzkvcarqquqslspul@forum.dlang.org

Yes, I remember that. That approach is still trying to somehow trick / patch (e.g. via some form of opDispath) the current D object system.

The LISP (CLOS) multi-methods approach is different: basically, you build the dispatch mechanism yourself; so everything is under the libraries' control.

This is essentially how openmethods.d Multiple Dispatch is done.


September 29, 2020
In reply to mw and jmh530:

I looked a bit at Eiffel circa 2000 and, to be frank, I didn't like it. I think that it belongs to the category of Object Obsessed languages, where everything is (has to be) an object, and every function has to be a member. This contradicts the philosophy behind openmethods and CLOS: methods live outside of classes, and polymorphic behavior can be added without modifying existing classes. Functionality found inside classes tend to be minimal - what Luís Marques describes as the "anemic domain models".

On the other hand, I like it that Eiffel has multiple inheritance. I did a bit of reading today and it seems to offer flexibility regarding shared and repeated inheritance. In particular, it is not decided by the direct subclasses (like with C++'s virtual inheritance) So there may be some good ideas to steal there.

September 29, 2020
On Tuesday, 29 September 2020 at 21:19:35 UTC, Jean-Louis Leroy wrote:
> In reply to mw and jmh530:
>
> I looked a bit at Eiffel circa 2000 and, to be frank, I didn't like it. I think that it belongs to the category of Object Obsessed languages, where everything is (has to be) an object, and every function has to be a member. This contradicts the

I don't like the Eiffel's pure OO treatment either: everything in the world has to be modeled as object, which does not always make sense.

> On the other hand, I like it that Eiffel has multiple inheritance. I did a bit of reading today and it seems to offer flexibility regarding shared and repeated inheritance. In particular, it is not decided by the direct subclasses (like with C++'s virtual inheritance) So there may be some good ideas to steal there.

The key idea is to treat each parent's class attributes individually (via rename/undefine/redefine/select) instead of as in other multiple inheritance languages, e.g. C++'s all-or-none approach, i.e. either all the parents' attributes are shared or separated, and even when separated, there is no proper renaming mechanism to handle it.

I still think the idea of combine Eiffel's multiple inheritance with CLOS like multi-methods is interesting: this basically is to use D as a target language, and completely build a new OO system on top of it.

September 29, 2020
On Tuesday, 29 September 2020 at 21:43:03 UTC, mw wrote:
> The key idea is to treat each parent's class attributes individually (via rename/undefine/redefine/select) instead of as in other multiple inheritance languages, e.g. C++'s all-or-none approach, i.e. either all the parents' attributes are shared or separated, and even when separated, there is no proper renaming mechanism to handle it.

If Base has features f and g, and Derived inherits from Base but undefines g, I assume that a Derived object cannot be substituted for a Base. Correct?
September 29, 2020
On Tue, Sep 29, 2020 at 10:02:28PM +0000, Jean-Louis Leroy via Digitalmars-d wrote:
> On Tuesday, 29 September 2020 at 21:43:03 UTC, mw wrote:
> > The key idea is to treat each parent's class attributes individually (via rename/undefine/redefine/select) instead of as in other multiple inheritance languages, e.g. C++'s all-or-none approach, i.e. either all the parents' attributes are shared or separated, and even when separated, there is no proper renaming mechanism to handle it.
> 
> If Base has features f and g, and Derived inherits from Base but undefines g, I assume that a Derived object cannot be substituted for a Base. Correct?

This would break Liskov Substitution, wouldn't it?

In any case, Eiffel-style multiple inheritance with undefine/redefine sounds to me more and more like a case of composition rather than inheritance. IOW you're not really dealing with subclasses that can be treated as instances of the base class anymore; you're dealing with pulling in {methods,fields,etc.} from the base class and arbitrarily modifying them to produce a new object that may or may not even substitute for the base class anymore in the Liskov sense.

Frankly, whenever I'm faced with this sort of free-for-all Lego-style object composition, I throw inheritance out the window and instead write my own infrastructure for object composition. Like an entity-component architecture or some such, that confers much more flexibility (and has cleaner implementation / saner semantics) than a free-for-all inheritance system.

I mean, sure, being able to undefine/redefine base class members is all nice and everything, but it's very hard to reason about. (Systems with erasure semantics are generally hard to reason about.) I'd rather make it explicit by representing it with an entity-component storage system than trying to shoehorn it into some kind of inheritance hierarchy with an arbitrarily-imposed hierarchical system. IME, objects that need arbitrary composition operations to define generally also fit poorly into a hierarchical system; I prefer using a true compositional system like ECS where (1) it's explicit what exactly you're trying to do, and (2) it's actually maximally flexible, in that you can add/remove arbitrary combinations of components to your entities, and (3) this can be done even at runtime, no lock-in to a specific memory layout.


T

-- 
Creativity is not an excuse for sloppiness.
September 29, 2020
On Tuesday, 29 September 2020 at 22:02:28 UTC, Jean-Louis Leroy wrote:
> On Tuesday, 29 September 2020 at 21:43:03 UTC, mw wrote:
>> The key idea is to treat each parent's class attributes individually (via rename/undefine/redefine/select) instead of as in other multiple inheritance languages, e.g. C++'s all-or-none approach, i.e. either all the parents' attributes are shared or separated, and even when separated, there is no proper renaming mechanism to handle it.
>
> If Base has features f and g, and Derived inherits from Base but undefines g, I assume that a Derived object cannot be substituted for a Base. Correct?

It still can; but the Derived now becomes a deferred- (in D's term abstract-) class.

because Derived.g becomes a deferred- (in D's term abstract-) method.


This is the demo:

https://github.com/mingwugmail/dlang_tour/tree/master/eiffel/mi

https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/us_resident.e#L3
  undefine addr

https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/app.e#L17
  create usr.make  -- ****** Warning: addr is a deferred feature in US_RESIDENT.

https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/app.e#L11
   print_addr(p: PERSON) is do
      io.put_string(p.addr + "%N")
   end



NOTE: I'm not sure if the SmartEiffel compiler is implemented correctly, it generate warning instead of error, during compilation:

$ make
compile  app.e -o app
****** Warning: addr is a deferred feature in US_RESIDENT.

And if you run it, it error out:

$ ./app
*** Error at Run Time ***: Deferred routine called.
4 frames in current stack.


Ideally, this program shouldn't compile; since it detected that we are trying to create an object of a abstract (deferred) class.


Hey, just download the SmartEiffel compiler, and try the demo :-) it's all in the same repo:

https://github.com/mingwugmail/dlang_tour/tree/master/eiffel

September 29, 2020
On Tuesday, 29 September 2020 at 22:18:52 UTC, H. S. Teoh wrote:
> On Tue, Sep 29, 2020 at 10:02:28PM +0000, Jean-Louis Leroy via Digitalmars-d wrote:
>> On Tuesday, 29 September 2020 at 21:43:03 UTC, mw wrote:
>> > The key idea is to treat each parent's class attributes individually (via rename/undefine/redefine/select) instead of as in other multiple inheritance languages, e.g. C++'s all-or-none approach, i.e. either all the parents' attributes are shared or separated, and even when separated, there is no proper renaming mechanism to handle it.
>> 
>> If Base has features f and g, and Derived inherits from Base but undefines g, I assume that a Derived object cannot be substituted for a Base. Correct?
>
> This would break Liskov Substitution, wouldn't it?

No, it just become abstract method, and class.

> {methods,fields,etc.} from the base class and arbitrarily modifying them to produce a new object that may or may not even substitute for the base class anymore in the Liskov sense.

Can you study the language behavior before making such comments?

This language won the ACM system software award!

> I mean, sure, being able to undefine/redefine base class members is all nice and everything, but it's very hard to reason about.

It's very easy, and nature to reason about it:

undefine a method Derived.foo() ==> Derived.foo() now becomes an abstract method.


Please see my previous reply.  And try it yourself:

https://github.com/mingwugmail/dlang_tour/tree/master/eiffel/mi

September 29, 2020
On Tuesday, 29 September 2020 at 22:45:02 UTC, mw wrote:
> It's very easy, and nature to reason about it:


s/nature/natural


September 29, 2020
On Tuesday, 29 September 2020 at 22:36:39 UTC, mw wrote:
> On Tuesday, 29 September 2020 at 22:02:28 UTC, Jean-Louis Leroy wrote:
>> On Tuesday, 29 September 2020 at 21:43:03 UTC, mw wrote:
>>> The key idea is to treat each parent's class attributes individually (via rename/undefine/redefine/select) instead of as in other multiple inheritance languages, e.g. C++'s all-or-none approach, i.e. either all the parents' attributes are shared or separated, and even when separated, there is no proper renaming mechanism to handle it.
>>
>> If Base has features f and g, and Derived inherits from Base but undefines g, I assume that a Derived object cannot be substituted for a Base. Correct?
>
> It still can; but the Derived now becomes a deferred- (in D's term abstract-) class.
>
> because Derived.g becomes a deferred- (in D's term abstract-) method.

Looking at your example, I have the impression that the `addr` "feature" is actually a function. If so, `undefine` in this example is simply the equivalent of tacking a `= 0` after an overridden virtual function in C++ (yes you can inherit an implemented virtual function and make it pure again). But, does this also work on attributes?

>
>
> This is the demo:
>
> https://github.com/mingwugmail/dlang_tour/tree/master/eiffel/mi
>
> https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/us_resident.e#L3
>   undefine addr
>
> https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/app.e#L17
>   create usr.make  -- ****** Warning: addr is a deferred feature in US_RESIDENT.
>
> https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/app.e#L11
>    print_addr(p: PERSON) is do
>       io.put_string(p.addr + "%N")
>    end
>
>
>
> NOTE: I'm not sure if the SmartEiffel compiler is implemented correctly, it generate warning instead of error, during compilation:
>
> $ make
> compile  app.e -o app
> ****** Warning: addr is a deferred feature in US_RESIDENT.
>
> And if you run it, it error out:
>
> $ ./app
> *** Error at Run Time ***: Deferred routine called.
> 4 frames in current stack.
>
>
> Ideally, this program shouldn't compile; since it detected that we are trying to create an object of a abstract (deferred) class.
>
>
> Hey, just download the SmartEiffel compiler, and try the demo :-) it's all in the same repo:
>
> https://github.com/mingwugmail/dlang_tour/tree/master/eiffel


September 29, 2020
Aw, sorry for the spurious quoting in my previous message...