Scoped binding of a method to an object

Brendan Eich brendan at mozilla.com
Tue Oct 15 15:04:13 PDT 2013


> Benjamin (Inglor) Gruenbaum <mailto:inglor at gmail.com>
> October 15, 2013 2:00 PM
> I think I misunderstood `::` before. if `a::b(x_1,...,x_n)` _just_ 
> means `b(a,x_1,...,x_n)`

No, rather: `b.call(a, x_1, ..., x_n)` but with the original 
Function.prototype.call (not any shadowing b.call).

> I think it might be a good solution to the chaining problem.
>
> I think the `.constructor` proposal as well as being able to do `::` 
> completely eliminates the need for extension methods in this regard. 
> It also behaves similarly to extension methods in C# in that it's 
> _just_ a static method and it could also introduce interesting options.

Indeed static methods with |this| uncurried are easier to call in the 
absence of ::, and this is why I added these so-called "static generics" 
to SpiderMonkey:

js> a = [1,2,3]
[1, 2, 3]
js> Array.map(a, x => x*x)
[1, 4, 9]
js> Array.reduce(a, (r,x) => r*x)
6
js> // etc.

Doing [].map.call(arraylike, mapfun) or worse, 
Array.prototype.map.call(arraylike, mapfun) is just no fun!

> The only issue here is:
>
> > Which polymorphism to people want? There is a "DWIM" aspect that 
> cannot possibly cover all uses of, e.g., 'draw' on the right of dot.
>
> Let's say I have a classic prototypical inheritance use case.
> Cat.prototype.meow = function(){...
> Kitten.prototype = new Cat()
> Kitten.prototype.purr = function(){ ....
>
> Now I have a catOrKitten object. If I define a `function 
> purr(catOrKitten)` and call `carOrKitten::purr()`

This is based on your misunderstanding corrected above -- :: binds the 
object to the left of :: to |this|, not to the first argument.

> regardless of it being a cat or a kitten - that function gets called. 
> If I had an extension method on Cat.prototype, I'd get the ""correct"" 
> behavior for kitten who overrides that method on its prototype.

I don't see purr on Cat.prototype --what am I missing?

Anyway, as Russell proposed, :: with imported *methods* (not |this|-free 
functions) is does call the named function, so without multimethods or 
any kind of dispatch based on arguments not receiver (this), you're 
right. You bind a method value to a name and call it on a given |this|.

Allen objected that this doesn't do receiver-based dispatch, which I 
think was your point with the cat and kitten. That's true, and SOE has 
that advantage -- kind of. SOE as I understand the strawman looks in the 
extension object first, and the extension object has no protototype 
object. It's flat. If you use an extension name on some other object 
that is not extended, of course you get polymorphic receiver-based dispatch.

/be


More information about the es-discuss mailing list