(How) does proto operator distiguish between function and non-function in LHS?

# Herby Vojčík (14 years ago)

The proposal for <| cites these usage examples:

  • Setting the prototype of a function to something other than Function.prototype

    let f = EnhancedFunctionPrototype <| function () {}

  • Parrallel constructor/instance prototype chains

    let superclass = function () {}; //define a constructor method superclass.new = function () {return (new this()).initialize()}; //define a instance method superclass.prototype.initialize = function () {return this}; let subclass = superclass <| function () {}; ...

Question: When RHS is function expression, does it distinguish if LHS is function to select one of the (different) behaviours from above?

# David Bruant (14 years ago)

Le 28/01/2012 09:28, Herby Vojčík a écrit :

The proposal for <| cites these usage examples:

  • Setting the prototype of a function to something other than Function.prototype

    let f = EnhancedFunctionPrototype <| function () {}

  • Parrallel constructor/instance prototype chains

    let superclass = function () {}; //define a constructor method superclass.new = function () {return (new this()).initialize()}; //define a instance method superclass.prototype.initialize = function () {return this}; let subclass = superclass <| function () {}; ...

Question: When RHS is function expression, does it distinguish if LHS is function to select one of the (different) behaviours from above?

The problem is that even if it did, it wouldn't be enough to say if the intention of the programmer was the first case (enhanced function prototype) or the second case (richer constructor), since a function on the LHS could be used in both cases.

I have raised the concern already and am not sure I have received an answer yet. I think 2 operators should be created. One for each case.

One question that could arise is: what if someone wants to build a function with a particular constructor behavior and an enhanced prototype (unrelated to the constructor it "inherits" from)? One answer could be that the 2 operators could be composed together.

# Herby Vojčík (14 years ago)

David Bruant wrote:

Le 28/01/2012 09:28, Herby Vojčík a écrit :

The proposal for<| cites these usage examples:

  • Setting the prototype of a function to something other than Function.prototype

    let f = EnhancedFunctionPrototype<| function () {}

  • Parrallel constructor/instance prototype chains

    let superclass = function () {}; //define a constructor method superclass.new = function () {return (new this()).initialize()}; //define a instance method superclass.prototype.initialize = function () {return this}; let subclass = superclass<| function () {}; ...

Question: When RHS is function expression, does it distinguish if LHS is function to select one of the (different) behaviours from above? The problem is that even if it did, it wouldn't be enough to say if the intention of the programmer was the first case (enhanced function prototype) or the second case (richer constructor), since a function on the LHS could be used in both cases.

Exactly, that was my concern, too.

I have raised the concern already and am not sure I have received an answer yet. I think 2 operators should be created. One for each case.

I would apply different, more cutting approach. Ditch the former completely. For functions, it is natural to inherit from functions.So that ultimately it leads to Function.prototype.

(Having jQuery) you can do $.extend(function(){}, x) <| function (...) {...} to achieve similar thing.

One question that could arise is: what if someone wants to build a function with a particular constructor behavior and an enhanced prototype (unrelated to the constructor it "inherits" from)?

Well, I would definitely say this is so special that "make simple things simple, make hard things hard" is appropriate and no helper would be there for the user. He can do it by:

var f = FunParent <| function (...) {...}; f.prototype = Object.create(protoParent, { constructor: { value:f, writable:true, configurable:true }});

One answer could be that the 2 operators could be composed together.

And it works in line with ditching the proto-for-function syntax.

# Allen Wirfs-Brock (14 years ago)

On Jan 28, 2012, at 12:28 AM, Herby Vojčík wrote:

The proposal for <| cites these usage examples:

  • Setting the prototype of a function to something other than Function.prototype

    let f = EnhancedFunctionPrototype <| function () {}

  • Parrallel constructor/instance prototype chains

    let superclass = function () {}; //define a constructor method superclass.new = function () {return (new this()).initialize()}; //define a instance method superclass.prototype.initialize = function () {return this}; let subclass = superclass <| function () {}; ...

Question: When RHS is function expression, does it distinguish if LHS is function to select one of the (different) behaviours from above?

from the proposal: "If the LHS operand has a property named prototype and the RHS operand is a function expression then the [[Prototype]] of the function object is set to the LHS object and the prototype property of the new function is set to a new object whose [[Prototype]] is the value of the LHS’s prototype property. Here’s a picture of what happens in this case: function "subclassing" UML diagram"

In other words, it uses the value of <LHS>.prototype to set the [[Prototype]] of the new prototype object. If no such property exists, [[Prototype]] of the prototype is set to its default value.

In all likelihood you would want EnhancedFunctionPrototype to be defined similarly to this example from (allenwb/ESnext-experiments/blob/master/ST80collections-exp0.js ) of doing something different: //define a non constructible superclass that provides some Smalltalk-like conventions const AbstractClass = Function.prototype <| { subclassResponsibility() {throw new Error(this.name+" did not implemented an abstract method")}, shouldNotImplement() {throw new Error(this.name+" should not implemented by "+this.name)}, name: "AbstractClass", prototype: Object.prototype <|{ get class() {return this.constructor}, error(message) {throw new Error(message)}, subclassResponsibility() {return this.class.subclassResponsibility()}, shouldNotImplement() {return this.class.shouldNotImplement()}, errorSubscriptBounds(index) {this.error("subscript is out of bounds: "+index)} } };