Bound instance-function vending (was RE: Arrow binding)

Brendan Eich brendan at mozilla.org
Mon Apr 23 13:07:27 PDT 2012


Domenic Denicola wrote:
> Hmm, so to make sure I understand: the getter-vending is more efficient because it only creates new functions when they are "gotten" (e.g. called or passed to a callback), whereas the closure pattern creates new functions for each instance? Or is there another reason?

That's one reason.

Even better would be a way to avoid creating a function per method per 
instance unless a method "get" (not "call") occurs. Calls that do not 
lead to reflection on the callee's identity as a function object should 
not need to create (and memoize, see below) a bound function for the 
method call. Only for extraction via get.

> It seems like, even if I did create 100 objects, if I called `method` twice on each of them, the closure pattern would win on efficiency.

No, in any such prototype-getter-makes-bound-function scenario, we would 
need memoization, so that

   o.m === o.m

(Edit: I see you mention this below.)

> I suppose it also helps enforce idiomatic expectations, namely that methods are on the prototype.

You mean by "it" getter-vending? Not really. The getter has to memoize a 
function bound to the instance on which the proto-property was "got". 
That must be stored somewhere. Simplest is to store on the instance 
itself, shadowing the getter. That makes getter-vending a lazy variant 
of the closure pattern.

Contrast to Smalltalk or Dart where classes preclude overriding, 
shadowing and deleting properties along the prototype chain. This 
enables separation of |this| from method lookup in a vtable, so there's 
no need for more than a vptr per instance (with single inheritance).

An aggressive JS VM could optimize likewise but would have to deoptimize 
whenever an observable change to the composite vtable due to  assignment 
(what I meant by overriding above), shadowing, deleting happened.

>   Then again it breaks the idiomatic (and I'd argue more basic) expectation that `myObj.method === myObj.method`, not to mention `myObjInstance1.method === myObjInstance2.method`.

That's not idiomatic. An idiom is a phrase such as "kick the bucket" 
where a non-English reader cannot divine the meaning from the 
constituent words.

Whereas method object identity invariance is kind of basic, not just for 
users poking about and saving a reference for later, but for efficiency.

> Both of these could be ameliorated with WeakMap caching, but of course virtually nobody is going to write that code. (Unless... time for yet another class library? Hehehe.)

Right. An elaborate simulation of vtables using proto-getters, weakmaps 
(for memos), shadowing in instances could be done, but who would use it?

If the idea is that ES6 or 7 has classes and the vtable optimization 
becomes more usable and easier for implementors, maybe. But such a 
system would not be equivalent to constructors with prototypes, and it 
would not observably use proto-getters vending memoized per-instance 
functions (because that is not the vtable optimization, rather it is the 
closure-pattern deoptimization).

So I don't buy that in the future everyone will use prototype 
getter-vending machines :-P. If in the future something new more like 
class-oriented languages with vtables under the hood emerges, it won't 
be fully compatible with prototypes as used in JS today. And that is a 
reason to doubt it will emerge, in my book.

/be

>
> ________________________________________
> From: Brendan Eich [brendan at mozilla.org]
> Sent: Monday, April 23, 2012 14:12
> To: Domenic Denicola
> Cc: Alex Russell; Russell Leggett; Erik Aarvidson; es-discuss Steen
> Subject: Re: Bound instance-function vending (was RE: Arrow binding)
>
> There's a big penalty even in optimizing VMs in adding (the same) method
> reference to every instance, vs. sharing it via a prototype. Binding
> |this| without new syntax, using whatever (closures, .bind), can be
> optimized but it's a challenge and mainly, users do not  do it.
>
> The functional-combinator OOP style Angus advocates, which relies on
> .call to delegate, is pretty but it's yet another discipline and not one
> I see catching on. The language doesn't make it any easier for users
> than for optimizing VM implementors.
>
> The pattern you show below, the "closure pattern", is advocated (e.g. by
> crock's book) and it is used. The cost doesn't matter at low object
> populations and it's pretty enough, besides being already there, that I
> agree it will be hard to beat in my view.
>
> /be
>
> Domenic Denicola wrote:
>>> Having done this dance a couple of times, let me suggest to you that the method form will *eventually* end up at a per-class getter on the prototype which vends an instance function which is bound. People will (reasonably) want binding of some sort.
>> This sounds lovely. I vaguely remember seeing it on es-discuss in the past (for one of the built-ins or proposed built-ins, maybe?). But never in the wild.
>>
>> I'm curious, though---what advantages does this have over simply setting the method as an instance property? I.e. how does it differ from the following pattern?
>>
>> function C() {
>>       var that = this;
>>       that.method = function () {
>>           console.log(that);
>>       };
>> }
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>


More information about the es-discuss mailing list