<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>Hi Andrew</div><div><br></div><div>I'm very very tempted to say - see we all agree! - and are just fighting about secondary things.</div><div>A few quick questions here, more comments later..</div><div><br></div><div>James</div><div><br></div><blockquote type="cite"><div>I think that my concerns about inheritance may be somewhat different from those of Kim and Michael; I'm less concerned with similarity to Java and with ease of implementation than with an inheritance system that is easy to describe, and yet still lets us do the wind variety of things that we have discussed. These include<div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>(1) composing initialization,</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>(2) inheriting initialization code,</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>(3) not generating new objects unnecessarily, only to drop them on the floor moments later,</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>(4) Allowing for extension to something like MI or trait composition, at a later time and in higher language levels,</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>(5) Allowing inheritance to work between class objects,</div></div></blockquote><div><br></div><div>I think we all want this, well perhaps other than (5). And I think we can get it all. </div><div>, </div><blockquote type="cite"><div>I'm going to propose that Grace include a new kind of object, which I'm going to call here a template object. (Yes, sure, you can call it a trait if you like.)</div></blockquote><div><br></div>or a class?<br><blockquote type="cite"><div><br></div><div>Template objects are real objects. Like types, they are meta objects, that is, they are used to describe, indeed to prescribe, the application domain objects. There are two "odd" things about templates:</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>(1) They are denoted by a special language syntax, which looks like this:</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span> <b>template</b> { <span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> c_<i>i</i> = epr</div><div><span class="Apple-tab-span" style="white-space:pre"> </span> <span class="Apple-tab-span" style="white-space:pre"> </span><b>var</b> v_<i>i</i> </div><div><span class="Apple-tab-span" style="white-space:pre"> </span> <span class="Apple-tab-span" style="white-space:pre"> </span><b>method</b> m_<i>i</i> { expr }</div><div><span class="Apple-tab-span" style="white-space:pre"> </span> <span class="Apple-tab-span" style="white-space:pre"> </span>e_<i>i<span class="Apple-tab-span" style="white-space:pre"> </span>// initialization code</i></div><div><span class="Apple-tab-span" style="white-space:pre"> </span> }</div><div><br></div></blockquote><div><br></div><div>is the order fixed here, or is it free? </div><div><br></div><div><br></div><blockquote type="cite"><div><span class="Apple-tab-span" style="white-space:pre"> </span> This is <i>exactly</i> the current object constructor, except that the word <b>object</b> is replaced by <b>template</b>. (It's likely that the </div><div><span class="Apple-tab-span" style="white-space:pre"> </span> keyword <b>template </b>can often be omitted, since it can often be inferred from the context, just like we can</div><div><span class="Apple-tab-span" style="white-space:pre"> </span> often omit the keyword <b>type</b>.</div></blockquote><div><br></div>OK so free then...<br><blockquote type="cite"><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>(2) Templates are nominally typed. So the <i>only</i> things of type Template are created by the above syntax, or by operations on </div><div><span class="Apple-tab-span" style="white-space:pre"> </span> templates (to be discussed, but including a single inheritance operation and perhaps the trait composition operations).</div></blockquote><div><br></div><div>not sure here. I'll accept it for now, but if they really were nominal, I think it breaks your interval example as the two templates would have different nominal types. But I think I know what you mean - perhaps something like singleton types?? - which is fine.</div><div><br></div><blockquote type="cite"><div>In these two respects, templates are just like types. It may be that templates, like types, also need to be parameterized.</div><div><br></div><div>In this proposed new world, objects are created, as they are now, by executing some code that looks like <b>object</b> { ... }, only now we call this "instantiating an object template" rather than "executing an object constructor". (Longhand, that's now <b>object template</b> { }, but we can omit the template keyword). </div></blockquote><div><br></div><div>would programs normally use "object" to make new objects (like Java's "new")</div><div>or would they call methods. This "object" isn't a method request, is it?</div><div><br></div><blockquote type="cite"><div>So, where's the beef?</div><div><br></div><div>The innovation is that an object carries its template around with it for the whole of its lifetime — just like a Java or Smalltalk object carries its class around with it. After an object has been created, we can ask it for its template, just as we can ask it for its type, thus: </div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>myObject.template<span class="Apple-tab-span" style="white-space:pre"> </span>or templateOf(myObject)</div><div><br></div><div>I'm not sure which is the better syntax; it should parallel that for getting a run-time type.</div></blockquote><div><br></div><div>right. to deal with vampires, myObject.template or mirrors.templateOf(Object)</div><div><br></div><div>do you think of this as as base-level operation or a metal-level operation -</div><div>i.e. when would people have to learn about templates (and "object") </div><div><br></div><blockquote type="cite"><div>Here's the key idea: we can then use this template to create more objects, or as the basis for inheritance, or for trait composition. For example</div><div><br></div></blockquote><div><br></div><div>sure. I'll try to rewrite these examples later...</div><div>have to go now</div><br><blockquote type="cite"><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>class</b> aMatch.successful(b, m) {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>inherits</b> templateOf(true)</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> bindings <b>is</b> public = b</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> matched <b>is</b> public = m</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> emptyness = <b>template</b> {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>method</b> size <b>is</b> requirement {}</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>method</b> isEmpty { self.size = 0 }</div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>method</b> notEmpty { self.isEmpty.not }<div><span class="Apple-tab-span" style="white-space:pre"> </span><b>method</b> ifEmpty(block) { self.isEmpty.ifTrue(block) } </div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>method</b> ifNotEmpty(block) { self.isEmpty.ifFalse{block.apply(self)}} <div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>method</b> ifEmpty(block)ifNotEmpty { self.isEmpty.ifTrue(block)ifFalse{block.apply(self)}} </div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>class</b> aSet.with(args*) {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> rep = aList.empty</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>uses</b> emptiness + enumerable </div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>method</b> size { rep.size }</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><br></div><div><br></div><div>Because the template contains the initialization code, the inheritance and using operations can combine the initialization code from several different templates and execute it on a newly created object.</div><div><br></div><div>I see two issues:</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>(1) <span class="Apple-tab-span" style="white-space:pre"> </span>The static typists will want to place restrictions on what templates can be used to create objects. These will be similar to </div><div><span class="Apple-tab-span" style="white-space:pre"> </span>those restrictions that we have placed on the inherits expression: the intent is that the compiler can figure out the </div><div><span class="Apple-tab-span" style="white-space:pre"> </span>value of a template statically. This means applying templateOf to a statically known value, or using a literal template,</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>or a combination (using trait +, inheritance) of other statically known templates, perhaps with method exclusion,</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>aliasing, etc.</div></blockquote><div><br></div><div>sure the "noinal" types do the work here</div><br><blockquote type="cite"><div><span class="Apple-tab-span" style="white-space:pre"> </span>(2)<span class="Apple-tab-span" style="white-space:pre"> </span>In general, templates will need to be parameterizable. For example:</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> aCartesianPoint = <b>object</b> {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>method</b> x(a)y(b) { </div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>template</b> {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>def x is public = a</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>def y is public = b </div><div><span class="Apple-tab-span" style="white-space:pre"> </span>print "nothing will be executed until an object is made from this template"</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>} </div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>class</b> colorPoint.x(x)y(y)color(c) {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>inherits </b>aCartesianPoint.x(x)y(y)</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> color = c</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>This means that templates will often be returned from methods, because methods are the only things that take parameters.</div><div><br></div><div>(1) and (2) may conflict. Mostly, Michael's "tail call" rule will work, I think, but this will need to be hammered out.</div><div><br></div><div>How is this different from what we have? In practice, maybe not at all. Conceptually, every objects now contains a template that describes not only its methods but also its defs and vars and its initialization code. It has always had most of that stuff anyway, because the implementation wants to share it, burt we have never talked about it at the level of the language. Now, I'm proposing that we do.</div><div><br></div><div>I think that we actually need the <b>template</b> keyword. Consider what happens if we change <b>def</b> aCartesianPoint above to be</div><div><br></div><div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>def</b> aCartesianPoint' = <b>object</b> {</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>method</b> x(a)y(b) { </div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>object</b> {</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span>def x is public = a</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span>def y is public = b </div><span class="Apple-tab-span" style="white-space: pre; "> </span>print "this will be printed whenever x()y() is requested"<div><span class="Apple-tab-span" style="white-space: pre; "> </span>}</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span>} </div><div><br></div><div>The difference is that aCartesianPoint.x(3)y(4) now answers a Point object rather than a template for a Point object, and consequently requesting x()y() on aCartesianPoint now prints the message </div><div><br></div><div><br></div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>class</b> colorPoint.x(x)y(y)color(c) {</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>inherits </b>templateOf(aCartesianPoint.x(x)y(y))</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>def</b> color = c</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span>}</div></div><div><br></div><div>We can still inherit from the result of x()y(), but we now have to request its template; the resulting colorPoint objects will look the same both ways, but the side effects will be different. That is, without the template, creating a colorPoint will have the side effect of creating aCarteianPoint, printing "this will be printed whenever x()y() is requested", taking its template, and then dropping the CartesianPoint on the floor. This is the behavior that we want to eliminate.</div></blockquote><div><br></div><div><br></div><div>so is the message printed in inheritance? </div><div>if so when / how</div><div>i.e. when does the template initialisation run..</div><div><br></div><br><blockquote type="cite"><div>Explicit templates avoid James's "vampires": if James give me an encapsulated object, I can grab its template, but that does not help me to grab its data.</div></blockquote><div><br></div>well we control templates the way we control mirrors...<div><br><blockquote type="cite"><div>Because templates can be returned from methods, we can choose templates dynamically. For example, suppose that I have code</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> upInterval = <b>object</b> anInterval.from 0 to 10 by 2</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> downInterval = <b>object</b> anInterval.from 10 to 0 by (-2)</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> anInterval = <b>object</b> {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>method</b> from(f)to(l)by(s) {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>template</b> { </div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>uses</b> enumerable</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> first = f</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> last = l<span class="Apple-tab-span" style="white-space:pre"> </span></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> step = s</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>method</b> do (block) { if (s > 0) then ... }</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><br></div><div>I might argue that this is bad style, and that anInterval should be a class, not a template, but there you are ... </div><div><br></div><div>Suppose that I decide to split the implementation of upward and downward intervals. I can do this without forcing the client to refactor:</div><div><br></div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>def</b> anInterval = <b>object</b> {</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>method</b> from(f)to(l)by(s) {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>if s > 0 then {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span><b>template</b> {</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>uses</b> enumerable</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>def</b> first = f</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>def</b> last = l<span class="Apple-tab-span" style="white-space: pre; "> </span></div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>def</b> step = s</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>method</b> do (block) { ... // code for upward interval }</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>} </div><div><span class="Apple-tab-span" style="white-space:pre"> </span>} else {</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>template</b> {</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>uses</b> enumerable</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>def</b> first = f</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>def</b> last = l<span class="Apple-tab-span" style="white-space: pre; "> </span></div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>def</b> step = s</div><div><span class="Apple-tab-span" style="white-space: pre; "> </span><b>method</b> do (block) { ... // code for upward interval }</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div><span class="Apple-tab-span" style="white-space:pre"> </span></div><div><br></div><div>Now the template that I get back from from()to()by(s) depends on the value of s, but since they both have the same template type, everyone should be happy.</div><div><br></div></blockquote><div><br></div><div>more later</div><div><br></div><div>j</div><br><blockquote type="cite"><div><br></div><div><br></div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span> </div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>Grace-core mailing list</span><br><span><a href="mailto:Grace-core@cecs.pdx.edu">Grace-core@cecs.pdx.edu</a></span><br><span><a href="https://mailhost.cecs.pdx.edu/mailman/listinfo/grace-core">https://mailhost.cecs.pdx.edu/mailman/listinfo/grace-core</a></span><br></div></blockquote></div></body></html>