On Jan 7, 2013, at 3:24 PM, Brendan Eich wrote:

> Allen Wirfs-Brock wrote:
>> Even if we think we should discourage direct calls to class objects (I think 
>> I'm now in that camp)
> 
> (Why so?)

(Assuming you've already read 
https://mail.mozilla.org/pipermail/es-discuss/2013-January/027864.html)

The split constructor/function call behavior of things like Number and RegExp 
is specified as two distinct procedures that are distinguish based upon the 
type of invocation. Basally Number represents two different procedures and 
which one to invoke is contextually determined at the call site. The  
implementation of this can work by have an alternative entry point, or a 
special flag parameter associated with each such callable target.  Regardless 
of how it is actually implemented it amounts to the the function Number really 
representing two different procedures.

There is arguably some elegance in being able to use Number and a handful of 
others as both a coercion function and as a factory for new objects. However, 
as a general rule, it is probably not such a good idea to allow any arbitrary 
function to really be two procedure with arbitrarily different behaviors.  I 
suppose you could call it a form or overloading, sdomething which I'm also not 
particularly a big fan of.  Generally, I think programs are easier to 
understand if each named entity has only a single meaning. 

When you move from the ES spec. to ES code there currently is no way to 
declaratively express that we have a two procedure function. You have to have a 
single function body and try to use a conditional statement to choose between 
two different code paths within the same body.  But there also is no 
communications channel that conveys to the function body which sort of call 
context was used for the invocation.  In the post linked above, I showed how 
analysis of the this value along with careful branding of instances and 
initialization state can adequately duplicate the effective specified behavior 
of something like Number without direct communication of the nature of the call 
site.  This is similar to the manner in which ad hoc  parameter overloading is 
accomplished by JS programmers.  Again, like overloading, it can be 
accomplished and in a few situations it is desirable, but in general its 
probably something that should be avoided.  So, as a "best practice" I would 
generally discourage new/call over-loading.

We could try to formalize it. One way would be to make a flag available in the 
function body that indicating the invocation style (perhaps via  predeclared 
name in the same scope as the function name).  Another way would be to have a 
mechanism (perhaps a @@call or @@new private symbol named property of the 
function) to associate a second code body with each function.  However, either 
of these introduce the sort of super/new confusion that Herby and Brandon were 
concerned about. If @@call is the code body used for new, a super() call within 
it needs to call the super class constructor's @@new code instead of its @@call 
code like would be used anywhere else.  In addition it is adding both Es 
developer complexity and implementation complexity to potentially all calls.

So, I suggest:

1) Constructor  normally  should only be used to perform instance 
initialization.
2) In rare circumstances, overloading techniques can be used to make 
constructor functions choose between performing initialization or  
non-initialization tasks.  However this should be generally discouraged.

Allen
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to