At 11:32 PM 10/20/98 -0700, you wrote:
>On Fri, 16 Oct 1998, Tyler Close wrote:
>> The third point is also irrevelant because
>> the type of method dispatch that E uses means that E will never be able to
>> use function tables anyway. (At the very best, E will have to use some form
>> of hashtable such as a wire.)
>I'm not clear why you said that -- exactly what kind of mechanism
>are you thinking of as a function table, and how does E preclude it?
>Could E use what you call function tables if the programmer provided
>extra static typing information in "define" expressions?
A function table is an array of function pointers. In a statically typed language such as C++, compatible types have compatible function tables, meaning that they have pointers to overrides of the same methods in the same position in the function table. When client code wishes to make a polymorphic method invocation, it simply calls the method located at a pre-arranged offset in the target's function table.
Since E resolves method invocations by matching the method name and # of parameters, it cannot make use of any pre-arranged compatibility amongst types.
This line of E will work for any object x which has a method called foo(). There is no way of knowing in advance where amongst all of x's methods that foo() is located. Conceptually, E will have to search the object x at runtime for a method named foo().
>And -- out of curiosity -- what is a "wire" as you use it here?
It is possible to optimise this conceptual search by using wires. A wire is a mapping from one index to another index, it is essentially a closed hashtable of ints. You do a hashtable-like lookup of the index you have, and the spot where you end up in the int array is the mapped-to index.
Here's a possible implementation of E method resolution using wires. When a new type is loaded into the E environment, E assigns an index to each new method signature declared by the new type. Any method signatures that have already been introduced by other types will reuse the previously assigned index. The E environment will then construct a wire, mapping these global indices to indices into the type's function table. The method implementations in the new type will then be JIT compiled to do a wire lookup, using the global index and the target object's wire, to get the required method pointer.
Anyways, this was all just a parenthetical comment, the point is that E will never be able to make use of compatibility amongst function tables, so this cannot be used as an argument in favor of inheritance.
>> Well, here's a vote for doing away with inheritance. Wow, think of the
>> millions of hours of developer time spent trying to create inheritance tree
>> taxonomies. Talk about a simple yet powerful language!
>So here finally is the response i have been intending to make
>to this particular line of discussion for some time, but haven't
>caught up to:
>I think the issue is nearly moot. In a strongly-typed language
>inheritance is a clearly-defined thing that gives you the specific
>feature of type compatibility. In a dynamically-typed language
>the whole issue is blurrier anyway.
>When you reuse code by aggregating, you essentially have to do
>delegation. And the only thing "inheritance" really is in this
>language is a convenience that automates some of the drudgery
>of delegation for you. That is, it's no worse than what you
Well, the idea is that you are wrong. A lot of people feel that it *is* worse than what you want. The root of the problem is that inheritance gives you more delegation than what you want. For even experienced programmers, it can be difficult to properly manage all of this hidden delegation.
Moreover, inheritance encourages the designer to reuse by widening the interface of an object. I think you can appreciate that this opens up a Pandora's box of difficulties. On the other hand, aggregation encourages the designer to reuse by narrowing the interface of an object. I think nudging the designer towards simplicity is a good thing.
>, and certainly important to the goal of presenting
>beginners with concepts they are familiar with.
Well, Mark decided to eliminate threading because he feels that despite familiarity, threads are a top source of headaches. I think I can make a convincing argument that more headaches have been caused by inheritance.
>What advantage could *removing* inheritance possibly give you?
Since Mark seems to have a deep respect for Bjarne Stroustrup, I'll borrow a line from one of his books: "A good language should whisper the design in your ear." I think that by removing inheritance, we give E something to whisper.