[Grace-core] Inheritance and Template Objects

Kim Bruce kim at cs.pomona.edu
Sat Apr 6 00:06:12 PDT 2013


I must admit that I am seeing this proposal as much more complicated than the alternatives.  As I understand it, the point is using templates to get initialization code for creating objects, with a slightly different syntax for actually creating the objects.  The operation of sucking out a template seems to be an attempt to extract a constructor so that one can inherit from an object.

To me, all of this is more easily done with classes, and perhaps the distinction between kinds of operations is clearer with a slight tweak to the syntax.

class C.m(a,b) {
    ....
}

class D.n(a,b,c) {
   extends C with m(a+b,c)  // notice replacement of C.m by C with m to indicate new object not being executed.
   ...
}

var o: DType := D.n(1,2,3)

So far, the class notation just seems simpler than using templates.

Now suppose there is an object defined directly

var ob = object {var ..., method ...}

If we really want to inherit from it, then I understand that Andrew would either implicitly or explicitly define a template that would be associated with ob.  To me, it seems simpler to at that point just refactor and write

class obMaker.new {var ..., method ...}
var ob = obMaker.new

Now inheritance would work as usual from obMaker. Student programs will be relatively short (< 20 pages of code), so this kind of refactoring should be trivial.

Here is a new question that has also to do with our current syntax.

Suppose I have 

class C.m(a,b) {...}

Can I also define

class C.n(a,b) {...}  ?

That is I use the same name for the class, but different names for constructors.  In general, C.m and C.n might return very different types of objects, but I could imagine this being a useful way of getting multiple constructors for a class generating a fixed type:

class Point.at(x,y) {
    ...
}

class Point.origin {
      inherits Point with at(0,0)
}

Now classes aren't themselves objects, but I could imagine these definitions as giving rise to 
object Point {
     method at(x,y) {object {...}}
     method origin {at(0,0)}
}

That is, Point becomes an implicitly defined factory object containing both constructors, even though they are defined separately.  Presumably for this to work, all classes would have to be defined in the same scope.  Alternatively there might be different factory objects defined in different scopes depending on what classes are in scope.

Because I tend to think in a class-centric way, I would likely only want to define inheritance on the class level rather than doing it in the factory object, though I suspect some of you might want to be able to handle inheritance inside there as well.

With multiple constructors, the inheritance could be done separately on all classes/constructors or it could be done just once:

class FatPoint.at(a,b)radius(r) {
    inherits Point with m(a,b)
    var radius := r
}

and then either

class FatPoint.originWithRadius(r) {
      inherits FatPoint with at(0,0)radius(r)
}

or

class FatPoint.originWithRadius(r) {
      inherits Point with origin
      var radius := r
}

To me, all of this is simple and familiar.  The semantics is exactly what we've been talking about, with constructor code of superclasses that are inherited from being run on objects created from subclasses.

Kim



On Apr 5, 2013, at 6:02 PM, "Andrew P. Black" <black at cs.pdx.edu> wrote:

> 
> On 5 Apr 2013, at 12:00 , Marco Servetto wrote:
> 
>> I'm not too sure to understand well this template idea, so sorry if
>> what I'm saying can be out of topic; however:
>> Is there any need to declare template explicitly?
>> That is, template objects are representing (in my understanding) the
>> "datastructure" of the class,
>> in the implementation they would even be "some representation for" the
>> abstract syntax tree of an object literal.
> 
> Yes
> 
>> What if every object literal is simply jointed with his template
>> object statically created at compile time?
> 
> Yes — it contains a pointer to the template object.   This is like a class pointer, but the template also contains the initialization code containing an unbound self parameter. 
> 
>> That is, when one write
>> def o1=object{....}
>> ...
>> def o2=object{ use o1.template .... }
>> o2 is created using the "soul" of o1.
> 
> Yes.
> 
>> "template objects" are objects the user can not (or may be can in some
>> dialect?) directly create and  observe; still they can be there, and
>> can be first class too (with some weird typing issues?)
>> And, of course, trait operators are simply messages over template objects.
> 
> I think that Marco understands what I had in mind.  Explicit use templates would not be necessary, because you could always get a template out of a prototype object (using the "soul sucking" operation).  But if one wants to think about inheritance pedagogically, then its desirable.  The difference between a class (which is used to make new instances) and a template (which is used to make new templates, via inheritance), and to define factory methods in classes (using instantiation), become important.
> 
> Looked at like this, the difference between templates and objects is as important as the difference between types and classes.   We could drake the language appear smaller by obscuring the distinction, but that won't actually make it simpler.
> 
> I don't know what James is trying too accomplish via his encodings.  As I said at the beginning of my original email on templates, I'm trying to get a clean conceptual model that I can write about in a textbook and that I can teach.  Once we agree on that, we can find a nice syntax that we like, hopefully one that is not very different from what we have been writing so far.   But I think that it' important to agree on the concepts first.
> 
> On 5 Apr 2013, at 16:17 , James Noble wrote:
> 
>> But in the template model, the templates are instantiated whenever they're inherited.
> 
> No, they are not.  You can compose two templates using inheritance (or using trait composition) without instantiating them.
> 
>> Or ... when writing  "object Template"
> 
> Yes, object <template> is the way that we would instantiate a template, creating an object that has that template as its "soul".
> 
>>> It's an explicit goal of mine not to have unnecessary incantations.  
>> 
>> Sure.  But the question then is whether we need a third concept -
>> a template - as well as objects and classes that we've already got
> 
> In this proposal, we don't need classes as a concept.  We can still have classes as a syntax, but they are just a shorthand for an object with a factory method, as they have been for a while.
> 
> I believe that we do need an additional concept to get conventional inheritance semantics.  The theory tells us that we do (the class generators as well as the classes that are their fix points), and Michaels' s "constructors parameterized by self" scheme tells us that we do.  My original "inheritance by copying" scheme was an attempt to avoid this, but didn't work exactly because the stuff that needs to be in an object is different from the stuff that needs to be executed in construction that object.
> 
>> What I'm trying to get to are the essential difference between the proposals ...
> 
> What I'm hoping for is a succinct explanation of the proposal that you have in your head that you are comparing templates to.   I think that it may be that it's the same as templates, except that the templateOf operation is implicit, and is applied whenever an object appears after the inherits keyword.  I don't think that's right, but then maybe I don't understand your proposal.
> 
> When I wrote 
> 
> 		def aCartesianPoint = object {
> 			method x(a)y(b) { 
> 				template {
> 					def x is public = a
> 					def y is public = b 
> 					print "nothing will be executed until an object is made from this template"
> 				}
> 			} 
> 		}
> 
> the idea was that aCartesianPoint.x(x)y(y) answered a template object, not a point object.  My example was bad, because colorPoint.x()y()color() did make colorPoint objects.  It would be more uniform like this:
> 
> 		def aColorPoint = object {
> 			method x(x)y(y)color(c) {
> 				template {
> 					inherits aCartesianPoint.x(x)y(y)
> 					def color = c
> 				}
> 			}
> 		}
> 
> So that aColorPoint.x(x)y(y)color(c) answers a template object too, not a point object.   Importantly, inheriting from aCartesianPoint.x(x)y(y) does not create aCartesianPoint; it's a template-level operation. 
> 
> We can then make instances directly from the templates, if we want:
> 
> 		def p = object aCartesianPoint.x(3)y(4)
> 		def cp = object aColorPoint.x(3)y(4)color(aColor.blue)
> 
> or we can make classes out of them:
> 
> 		def pointClass = object {
> 			def origin is public = object aCartesianPoint.x(0)y(0)
> 			method x(a)y(b) { object aCartesianPoint.x(a)y(b) }
> 		}
> 
> 
> 		def colorPointClass = object {
> 			def origin is public = x(0)y(0)color(aColor.black)
> 			method x(a)y(b) { x(a)y(b)(aColor.black) }
> 			method originColored(c) { x(0)y(0)color(c) }
> 			method x(a)y(b)color(c) { object aColorPoint.x(a)y(b)color(c) }
> 		}
> 
> Yes, there is a certain amount of repetitive code here.   That's why (to my mind) we introduced the class syntax in the first place; to simplify the syntax of such common operations.   I'm quite prepared to see us redesign the syntax a bit to eliminate some of the verbosity.  But I want to agree on the underlying semantics first.
> 
> In contrast, with this definition, 
> 
>> class aCartesianPoint.x(a)y(b) { 
>> 					def x is public = a
>> 					def y is public = b 
>> 					print "this string will be printed each time the x()y() method is executed"
>> 			}  
> 
> 
> requesting the x()y() method on aCartesianPoint will make an actual point object, and also print out the string.
> 
> If we go in the direction that I'm proposing, I think that we do need to be careful to be uniform in our naming.  It's a Bad Idea (capital letters) to have operations like x()y() answering both templates and instances.   And its a Bad Idea (capital letters) to use aFoo for a template-generating object and aBar for an instance-generating object.  But now it's time for me to go and cook dinner.
> 
> 	Andrew
> 
> 
> _______________________________________________
> Grace-core mailing list
> Grace-core at cecs.pdx.edu
> https://mailhost.cecs.pdx.edu/mailman/listinfo/grace-core

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailhost.cecs.pdx.edu/pipermail/grace-core/attachments/20130406/696a28bf/attachment-0001.html>


More information about the Grace-core mailing list