[Grace-core] Dialect Design Proposal

James Noble kjx at ecs.vuw.ac.nz
Wed Nov 28 03:42:25 PST 2012


> It seems clear to me that if we are to support stateful modules, then the default should be that there is only one that is shared.  (Given that default, we could clearly program to get separate copies of state if we wanted them.)

yes, I think we're mostly agreed on this. 

> We seem to be at a bit of a standoff here with strong differences in what is desired for the language.  I believe that it is essential that we support the standard semantics for classes and inheritance -- in particular that messages to self in the construction of an object refer to that object and not to some superclass object.  When I teach this material I will use that semantics, and I believe that we will have even less chance of a buy-in from instructors if we don't support that semantics.

So the current design has the "superclass" and "subclass" objects being the *same object* - the previous design did not - 
however before the sub-object-constructor has executed, behaviour will be that of the super object. I think.
For example, this code prints "TOP" then "BOT".  

class top.new {
    method x {print "TOP"}
    x
}

class bot.new {
    inherits top.new
    method x {print "BOT"}
    x
}

bot.new 


> As Andrew has pointed out, inheritance from objects has issues.  No doubt this explains why it generally doesn't show up in mainstream languages.

yep.

>  James points out below that this is supported by Self and Javascript, but they are prototype based.

and, in practice, Self had issues too. I know less about JS, but I don't think we'd want to emulate it either.

>  At this point, I'm confused enough that I'm not even sure any more what the intended semantics is for inheritance from objects.  Is it sharing (essentially some variant of delegation) or does it involve some sort of implicit clone (though I'm not sure what kind)?  Perhaps someone can point me to an e-mail that proposes exactly what it should be.

I don't think there as been such an email, although there have been emails about discussions.
I think implicit (shallow) clones are bad.  Explicit clones result in something pretty close to the "fresh objects"
design that we already have - expect that all "inheritable" objects would need to support a clone method,
that method would have to be built in, and so we now have two primitive generative mechanisms
(generative object constructors, and clone).  So far we've survived without clone, right?

> I'm getting frustrated enough to suggest maybe we should support both of these semantics by different syntax.  One instructor could choose working with classes and classical inheritance, while another could choose working with objects and some sort of delegation (perhaps using "sharing" instead of "inherits").  Both clearly have some uses, and neither seems easily definable from the other (and I fear what error messages would look like if we tried to define them that way).

that's one option - although it is the classical "design by committee" solution: put everything in. 

> I'm not happy with this solution, but I'd be even more unhappy to throw out the standard semantics of inheritance.  Andrew would be very unhappy if we threw out inheritance from objects.

I don't know if I'd be very unhappy, but I'd certainly be unhappy with two similar but subtly different inheritance-like mechanisms.
If we must have two mechansism, make them as brutally different as possible! 

>  Is there anything that might bridge the gap that doesn't make everything worse?

I don't know.  O'CAML style initializers? 
Explicitly building objects with mirrors (sounds to close to macros to me)?
Traits / FJigsaw style object construction?

How bad would it be if clonable objects either had to inherit from "Clonable" (or - potentially worse) had to have a Clonable annotation?

Then you could at least do something like this: 

def myTrait = object {
  extends Clonable.clone /// have to clone or we corrupt the Clonable trait object! 
  method foo {...}
  method bar {...}
}


class myClass.new {
     extends myTrait.clone // again must clone to avoid prototype corruption problem
}

extending this model to multiple inheritance is... trickier.  
And there is very little difference with this: 

class myTrait.new = object {
  method foo {...}
  method bar {...}
}

class myClass.new {
     extends myTrait.new
}

in fact I think the class version is better overall...

James


More information about the Grace-core mailing list