<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Aug 5, 2011, at 12:14 PM, Brendan Eich wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On Aug 5, 2011, at 9:32 AM, Allen Wirfs-Brock wrote:</div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>I did something similar in my first go at this, but there is a problem...</div></div></div></blockquote></div><br><div>Right, the desugaring from class syntax is fragile and error-prone. </div></div></blockquote><div><br></div><div><div>I not so sure I agree.  It isn't obvious that this code pattern is particularly any more fragile, error prone, or less toolable than some of the class syntax alternatives that have been discussed.  Particular, if a programmer sets up an editor template that inserts:</div><div><font class="Apple-style-span" face="'Courier New'">const classname = subclass <| function ( ) {</font></div><div><font class="Apple-style-span" face="'Courier New'">   super.constructor();</font></div><div><font class="Apple-style-span" face="'Courier New'">   this.{</font></div><div><font class="Apple-style-span" face="'Courier New'"><br></font></div><div><font class="Apple-style-span" face="'Courier New'">   };</font></div><div><font class="Apple-style-span" face="'Courier New'">}.prototype.{</font></div><div><font class="Apple-style-span" face="'Courier New'"><br></font></div><div><font class="Apple-style-span" face="'Courier New'">}.constructor.{</font></div><div><font class="Apple-style-span" face="'Courier New'"><br></font></div><div><font class="Apple-style-span" face="'Courier New'">};</font></div></div></div></div></blockquote><div><br></div>Let's count the hazards and costs:</div><div><br></div><div>1. No hoisted binding.</div></div></blockquote><div><br></div><div>I think hoisting classes may be problematic anyway.  Hoisting really isn't need to make forward class references from within method bodies work.  Outside of methods bodies hoisting allows oddities such as:</div><div><br></div><div>class First {</div><div>class:</div><div>  partner: new Second();  //or what ever a data property definition looks like in a class def</div><div>  defaultInstance: new First;  //is this legal</div><div>}</div><div><br></div><div>class Second{</div><div>  constructor() {</div><div>     this.friend = First.defaultInstance;</div><div>  }</div><div>}</div><div><br></div><div>or even inheritance circularities.  It isn't obvious to me that there is any actual utility in hoisting class declarations.</div><br><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><br></div><div>2. Boilerplate overhead of "const D = B <| function" vs. "class D extends B": 1+2+8=11 vs. 7 (ignoring spaces). Arrow function syntax helps but you still end up with <|...-> cussing.</div></div></blockquote><div><br></div><div>I'd argue that the verboseness of "function" is largely an orthogonal issue.  Because <| requires (currently) a literal on the RHS the "function" keyword could conceivably be dropped in that context.  However, I don't think I'd want to advocate for that.  In the end, I don't that 4 does 4 characters would be a significant issue for anybody.</div><div><br></div><div>(BTW, does it bother anybody that the meaning of "extend" to mean "subclass of" in such class declarations is quite different from what seems to be the most common meaning (add properties to an object) of a function named "extend" in JS libraries and frameworks.)</div><br><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><br></div><div>3. As you already mentioned contra Axel, one cannot transpose .prototype. and .constructor. parts. Worse, if you don't have class methods, you have to end with a runt .constructor followed by a ;.</div></div></blockquote><div><br></div><div>My argument is that once you learn the pattern this isn't an issue.  Certainly, I didn't find my self having any issues with this when writing the collection code.  But, if this is really a work for you, here is a possible solution.  Define this function:</div><div><br></div><div>function Class(anObj) {</div><div>   if (anObj.hasOwnProperty('constructor)) return anObj.constructor;</div><div>   return anObj;</div><div>}</div><div><br></div><div>You could even put it as an export into a built-in module.</div><div><br></div><div>You can then say:</div><div>const C=Class(A <| function B() {</div><div>     ...</div><div>}.prototype.{</div><div>});</div><div><br></div><div>or put the constructor methods before the prototype methods if you prefer).</div><br><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><br></div><div>4. Braces required instead of no braces for section labels.</div><div><br></div></div></blockquote><div>I agree that there is a small cost associated with composeable primitives. But also that the composeability is worth the cost.</div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><br><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div><div>It isn't clear why this is necessarily any more fragile (or less temptable) than for example:</div><div><br></div><div><div class="gmail_quote"><div><div><font face="'courier new', monospace">class classname extends superclass {</font></div><div class="im"><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; ">  constructor() {</span></div></div><div class="im"><div><div><font face="'courier new', monospace">    this.  =  ;</font></div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; ">  }</span></div></div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; "><br></span></div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; ">prototype:</span></div><div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; ">class:</span></div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; "><br></span></div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; ">}</span></div></div></div></div></div></div></div></div></blockquote><div><br></div>Really? Item (3) is a big hazard. Readability is harmed by the cussing and bracing. The class syntax may not be the best sugar, but it is sweeter and (due to the order requirement of .prototype. before .constructor., and the mandatory .constructor at the end if you don't have class methods) safer.</div></div></blockquote><div><br></div><div>I think the Class function I suggest above could be an answer.  But exploring this was my motivation in writing a significant amount of code using my pattern.  I personally didn't find it awkward, error-prone, or to present any readability issues.  But that is all subjective.  If somebody should translated that corpus into class declarations we can do a side-by-side comparison of readability.</div><div><br></div><div>Allen</div></div></body></html>