Operator overloading revisited

Brendan Eich brendan at mozilla.com
Wed Jul 1 07:04:26 PDT 2009

On Jul 1, 2009, at 12:48 AM, Christian Plesner Hansen wrote:

>> (1) seems avoidable, though -- *assuming* it is not a phantom cost.  
>> We have
>> to deal with the symmetric vs. encapsulated issue, though. But  
>> notice that
>> Christian's proposal does not use "this" in the method bodies!
> The really nice thing about this from a cost standpoint is that it
> caches well.  If changes to the operators understood by an object are
> reflected in the object's hidden class (to use v8 terminology) the
> same way changes to methods are, all the same caching techniques can
> be used.

Implementations can optimize whether Function.defineOperator binds  
internal "this+" and "+this" or adds a multimethod.

> A global (hidden class, hidden class, operator)->function
> cache can be used to ensure that the full operator resolution only has
> to be done once for any operand type pair, after which the result can
> be fetched by a simple hash table lookup.

This cuts both ways. A multimethod reifies that "global" (lexically  
scoped, rather) cache.

>  Similarly, inline caching
> can ensure that the hash lookup only has to be done once for any
> monomorphic call site; megamorphic call sites, which I would expect
> were rare, would have to do a hash lookup but not full operator
> resolution.

> By the way, did you say "mutual-asymmetric multimethod" :-)?

Sorry, I kept typing "asymmetric" when I meant "symmetric". Tired here  
(new baby at home :-)).

Adding "mutual" didn't help, did it? I was trying to capture the  
reciprocal "this+"/"+this" intersection requirement. But it still  
seems to me any such internal properties should constitute an  
unobservable specification/implementation device.

Below you allow for internal properties, so presumably ("this+" in a)  
would *not* evaluate to true for (a + b) in your examples. So why  
require"this+" and "+this" bindings at all? Caching under the hood is  
still doable but it is an implementation detail.

> Methods live on objects and their prototypes.  Operators should too.

That's dogma, and it doesn't prove itself to unbelievers.

Why should operators be methods? Binary operators have no  
distinguished receiver. Indeed your proposal has nice generic  
functions for addition, no |this| at all. So much for "methods".

Saying that methods should "live" (be bound) somewhere when they do  
not use |this| to denote the receiver in which they are bound  
(directly or on the prototype chain) seems like even weaker dogma.  
Mark's double-dispatch is consistent with OOP. Your proposal seems to  
require reciprocal external property mutations on prototypes but only  
so the dispatch algorithm can do its simplified CPL thing. Why?

> Using a special internal property rather than plain old properties is
> fine by me but they should be directly associated with the objects
> involved.

Directly? You wrote "and their prototypes" above, and your  
Function.defineOperator examples were passed constructors (from which  
to mutate prototypes), not direct instances:

  Function.defineOperator('+', Point, Number, pointPlusNumber);

>   I'd argue why that is so important but I'd like to be sure
> I understand what you're proposing as an alternative.  As I understand
> it you would associate the operators with the constructor functions
> similar to python's five minute multimethods.  Is that correct?


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20090701/55651745/attachment-0001.html>

More information about the es-discuss mailing list