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