[E-Lang] pending revision of E in a Walnut

Mark S. Miller markm@caplet.com
Sun, 26 Aug 2001 18:59:05 -0700


At 04:10 PM Sunday 8/26/01, Marc Stiegler wrote:
>In E, the class declaration
>
>class objMaker() :type {...}
>
>is just syntactic shorthand for
>
>def objMaker {
>    to new() :type {...}
>}

The expansion is actually more complicated, in order to allow another 
"class" to "inherit" from objMaker.  The actual expansion is explained at 
http://www.erights.org/elang/blocks/inheritance.html .  However, if objMaker 
does not internally use the variable name "self", then the expansion is 
equivalent to the above, with the only remaining difference being that 
objMaker also responds to an "adopt" message with one more argument than 
the "new" message (the first "self" argument) which would then be ignored, 
and otherwise be equivalent to "new".


>So you can virtualize it just the way you virtualize anything else, and
>properties of initialization work the same way they work for anything else.

Correct.

>> Second, I wonder whether there aren't security implications of treating
>> the arguments to the constructor as instance variables.  Does this make it
>> easy to forget to make copies of them?  Will this lead to subtle problems
>> with wall-banging or other kinds of leakage, since the object the client
>> supplied is known to be the one held by the object?
>
>I haven't seen a security issue with it. [...]

I am also failing to understand what you might be worried about here.  
Please try again?


>> Under "Inheritance", you say "Some experts consider inheritance to be a
>> dangerous feature of programming languages [...]".  Does this statement
>> apply only to implementation inheritance?  Because I consider type
>> inheritance to be the root of polymorphism, which seems to me to be the
>> source of most of the power and benefits of OOP.

Before answering, I'd like to change this terminology.  

"Type inheritance" is a peculiar notion that I find confusing.  Instead, 
there is "subtyping", as when one Java interface extends another.  And there 
is "runtime polymorphism", as when several different implementation can 
implement the same type, and the same message send in the code can invoke 
different methods depending on the runtime implementation (or class, but not 
type!) of the object.  In Java, this happens when several classes implement 
a method declared in a supertype.  (Ignore that, in Java, the supertype may 
be either a class or interface declaration.)

"Implementation inheritance" is a fine term for what I would normally just 
call "inheritance", but in this note I'll say "implementation inheritance" 
to avoid confusion.  This is happens in Java when one class extends another, 
and uses some of the *behavior* defined by the superclass to provide its own 
behavior.

E does not really have declared types, so it doesn't really have declared 
subtyping.  However, E has gobs of runtime polymorphism.  Not having 
declared types, E's polymorphism is name-based, as is Smalltalk's.  In 
Smalltalk, the method name also determines the arity of the message.  In E 
it does not, so E polymorphism and method dispatch is based on the name and 
arity of the message.

(Hal Finney has pointed out that there's a security price to be paid by 
using name-based, rather than type-based polymorphism.  (See his analysis of 
the flaws in the ERTP-aware MintMaker code.)  These are not fatal, but do 
require more care in order to avoid falling into these pits.  Fortunately or 
unfortunately, having set out on the non-statically-typed rapid prototyping 
path of language design, we must learn to live with this weakness rather 
than avoiding it.  I believe this cost is still cheaper than strong typing, 
but would be happy were someone to create a strongly typed E derivative that 
proves me wrong.)


>> Later in that paragraph you say "none of the full-blown examples in this
>> book actually use inheritance."  

I distinguish between simple delegation and full blown implementation 
inheritance according to whether there is a message pathway analogous to the 
"self" pointers shown in the diagram on 
http://www.erights.org/elang/blocks/inheritance.html .  Delegation allows 
the derived behavior to make use of the base behavior.  The "self" pathway 
enables this base behavior to in turn be parameterized (typically by 
overriding, but see Beta) by further derived behavior, as in the example's 
getFoo().

(Btw, by my earlier definitions, even simple delegation is a form of 
implementation inheritance.  I'm happy with that, so long as we distinguish 
it from full blown (or classic) implementation inheritance, which should 
usually be avoided.)


>I guess that reminds me that I haven't seen much use of polymorphism.

Strange, and an artifact of choosing small examples.  E is as pervasively 
polymorphic as Smalltalk.


>  (Other than in the coordinate spaces code
>> MarkM sent as part of a different discussion, but I haven't figured out
>> how that works yet.)

Let's do lunch.


>> I realize that E doesn't have strong typing, but if
>> it also deemphasizes polymorphic types, I'm likely to be disappointed.

Don't worry!  Be happy!


>> Why is this section here?  Do you have an aversion to type hierarchies or to
>> polymorphism?  If not, I'd suggest being clear what aspect of inheritance
>> you're advising people to avoid.  If that is the point, I'd like to hear
>> what I've been doing wrong all these years. :-)
>
>It's the type hierarchies that cause religious wars here in the e-lang list.
>In E in a Walnut, if you just search for each usage of "delegate {", each of
>those is, I believe, a usage of polymorphism. 

Terminology confusion.  Each of those is a usage of delegation.  MarcS, how 
about an explicit example of runtime polymorphism in the next Walnut?

The book is advising against usage of the "adopt" / "self" notions provided 
by the class sugar, or patterns of delegation morally equivalent to these.  
Where inheritance is normally used, delegation + explicit parameterization 
(rather than overriding) is usually better.

Since programming in E, I have come across exactly one example for which 
classic inheritance is exactly the right pattern: specializing a copy 
visitor.  I'll leave that one to another email message.


        Cheers,
        --MarkM