Good-bye constructor functions?
allen at wirfs-brock.com
Mon Jan 7 17:50:04 PST 2013
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.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the es-discuss