Function.prototype.bind

Brendan Eich brendan at mozilla.org
Wed Sep 10 00:49:50 PDT 2008


On Sep 9, 2008, at 11:51 PM, Mark S. Miller wrote:

>> LSP is not preserved by many cases in OO languages. Is it  
>> important here?
>
> I think it's a valuable property

It's come up before, but is it a sacred cow? Method overriding in  
classical OOP breaks it. Undeclared exceptions are another hard case.  
Not that we're ready for inheritance with overriding in any "classes  
as sugar" proposal (yet!), and we should never add declared  
exceptions (please! ;-)).

I'm willing to rename Function.apply, but let's talk some more about  
the better name, and about why it matters.


> Why ducking? If this operation is needed,

Do you think it's not needed?

Some method of applying callable objects that aren't functions, where  
the new method does not depend on Function.prototype.apply, is  
necessary in our experience. You could try to stick to  
Function.prototype.apply and add integrity by providing a frozen  
standard library object with Function in it, but writing  
Function.prototype.apply.call(callable, thisobj, argsarray) is  
painful, and frozen standard library object is bloat we may not want  
in any case, certainly not just to solve the problem David-Sarah cites.

There are other ways to provide a frozen apply-any-callable function,  
but the point is that something is needed beyond the replaceable  
Function.prototype.apply slot.

> I think a different name is exactly the right solution.

Could you suggest a new name?

LSP means none of the static generics proposed for Function should  
have the same name as their Function.prototype counterparts (apply,  
bind, call -- abc). We could just mangle them all with some prefix,  
Garrett just suggested "call": callApply, callBind, callCall. Ugly,  
arguably less usable in practice than the LSP violation you point out  
(I'm skeptical that Function would ever by .apply'ed indirectly), but  
doable. Better name ideas welcome.

I'm to blame for this LSP violation, but in my defense I'll say that  
it was not intentional. I don't think of Function as a function,  
rather as a constructor. Constructors can't be .apply'ed when invoked  
via operator new -- a bug that the proposed and so-far warmly- 
received spread operator solves nicely:

   new callable(...argsarray)

Note no explicit |this| parameter for constructors, so spread does  
not solve the Function.prototype.apply problem for plain calls:

   Safe.universalApply(callable, thisobj, argsarray)

can't be rewritten as:

   callable(this=thisobj, ...argsarray)

as Tucker suggested recently (he used receiver=, but I still think  
this assignment is better, since it's illegal currently and it avoids  
adding a new contexually reserved word -- detail!).

Still, if we had spread, would we be bothering with Function.apply,  
or with those pesky strict mode arguments tweaks? Food for thought.  
Sometimes adding new syntax avoids silly name mangling and  
unnecessary modalities.

/be


More information about the Es-discuss mailing list