tc39 / proposal-operator-overloading

MIT License
618 stars 20 forks source link

Why is the explicit with declaration required? #3

Open peey opened 5 years ago

peey commented 5 years ago

Most languages in which I've seen operator overloading carry out overloading via types. If I do A + B then I use a + function defined on A's class (whatever A's type is at runtime).

This means that operators are seen as a syntactic sugar for A.plus(B).

Operator overloading is only enabled for the classes that you specifically opt in to.

Is there a specific reason for this?

trusktr commented 4 years ago

I think the reason is because JavaScript is not pre-compiled, it is interpreted at runtime.

If we didn't have to explicitly opt into operators within a module (or within a scope of some kind like a function scope), then every time the JS engine ran into an operator (like + for example) it would have to do a runtime check of the operands to see if they have operator overloads. It would be expensive to do this all the time for every single operator in any code that ever runs.

So, to avoid this, one must explicitly opt into overloads within some scope, so that the runtime checks are limited to that scope (and not the entire application code).

With compiled languages, the overloaded operations are simply encoded into the build output, statically, and don't need to be discovered at runtime, so that's why in compiled languages we can define operator overloads on our classes and be done with it.

littledan commented 4 years ago

Python is interpreted but has general operator overloading without these declarations. Mitigating performance impact is a lower-order reason in my mind; the higher-order reason is ensuring the integrity goals. It's on my todo list to explain these better than the README currently does, but see "predictability" under the "goals" section.

peey commented 4 years ago

@trusktr if performance is the goal then using with doesn't seem like a good solution.

If it's enabled at a module level, then all native accesses to + in the module will still bear the typechecking overhead.

I think you'd rather want to rely on JIT compilation for optimization.

peey commented 4 years ago

@littledan I think I agree with the goals stated under Predictability

  • The meaning of operators on existing objects shouldn't be overridable or monkey-patchable, both for built-in types and for objects defined in other libraries.
  • It should not be possible to change the behavior of existing code using operators by unexpectedly passing it an object which overloads operators. (If this is feasible.)

But does it then mean operators are not first-class functions? Semantically, are they something "special" with no counterparts in existing language features or other proposals?

trusktr commented 4 years ago

Predictability is definitely good. I think performance matters too though. Seems we can have both if we declare which operators are used within a lexical scope?

TurtleKwitty commented 3 years ago

It doesn't feel like the impact on performance should be that high; if objects have a pointed to their operator based functions and that gets called with the right hand operator as the argument it would at worst be a single dereference more than what is currently done. Between on load verifying once if the class uses operator o reloading and therefore activating this mechanism for this class it shouldn't affect any code that doesn't use it in the first place and only very minimal overhead for the things that do, no?