[Grace-core] Super-Outer-Objects: What does your language (gBeta/Newspeak/Scala/Java…) do with this? What should Grace do?

James Noble kjx at ecs.vuw.ac.nz
Wed Nov 21 17:27:13 PST 2012


On ramifications of inheritance:

On 20/11/2012, at 06:35 AM, Andrew P. Black wrote:

>> 3.   def A = object {
>> 4.       method pathological {print "A-pathological"}  
>> 5.       def B = object {
>> 6.            method foo {pathological}
>> 7. 	   }
>> 8.   }

>> 10.  def C = object { 
>> 11.            inherits A.B

> (A has an auto-generated method B because of the  #pragma DefaultVisibility=public; this seems to be irrelevant to the example, since B could just as well be declared as a method directly, but perhaps James will explain why he did it this way.) 

So I wrote it this way mostly because of habit: this seems to be the way we generally write object literals in Grace.

An auto-generated method returning the value of a def is different from a method with an object literal in its body in one very important way: the single object in the def will be returned from each call to the "auto-generated" method, while a straight method will return a fresh object each time.   So actually the example shouldn't work: A.B isn't "fresh" and we shouldn't be able to inherit from it. 

> A somewhat tricker question might involve an D inheriting from A that overrides pathological.  What will D.B.foo print?  

Yep. I'll tackle that below, but my somewhat parenthetical point applies here too:  doing the obvious thing:

def D = object {
   inherits A 
   ...

is the _wrong thing_ because, under the concatenative inheritance model, 
D.B is the *same object as C - because, well A.B and C are the *same object*

if you add a "whoami" method to A.B, override it at C,  you can see the behaviour of the A.B object change
after C inherits from it.  Of course this is only observable because A.B isn't "fresh"

> The answer differs depending on whether we understand "pathological" in foo as being outer.pathological or A.pathological. I'm a bit worried about bizarre interactions and difficulties if it is bound to outer.pathological.  Thus an excess of caution leads me to bind it to A.pathological, even though that limits expressiveness.  

Changing all the defs to methods (code below) prints the same output (I hope!) 
and means we can inherit safely from A or A.B - and the whoami methods show 
that A.B.whoami does *not* change after it is inheriting and whoami overridden, because,
what is inherited is a different object.

> The other choice leads us awfully close to family polymorphism, which has its own issues.

well right. But especially given concatenation semantics for inheritance, I find a "lexical" choice
hard to justify.  For a start, inside the B.foo method, currently writing "A.pathological" is a 
"public" request to A (sees only public methods), while "outer.pathological" is an outer request.
The only construct we have that can bind into the "middle" of an other object is a "super" request:
are we sure we want to add to that menagerie?

James

(I'm still not sure I like the "auto-generated" story, but that's for another day…)







================================
this works but is convoluted, I think to avoid a compiler bug
================================

#pragma DefaultVisibility=public

method A {return object {
 method whoami {print "A"}
 method pathological {print "A-pathological"}  
 method B {return object {
  method whoami {print "B"}
  method foo {pathological}
}}
}}

A.whoami
A.B.whoami

method C(x) {return object { 
 inherits x
 method whoami {print "C"}
 method pathological {print "C-pathological"}
}}

A.whoami
A.B.whoami
A.pathological
A.B.foo
C(A.B).pathological
C(A.B).foo



More information about the Grace-core mailing list