Operator overloading was discussed here before: Mark Miller's strawman proposal (double dispatch) https://mail.mozilla.org/pipermail/es-discuss/2009-January/008535.html
Christian Plesner Hansen's "symmetric" operator overloading https://mail.mozilla.org/pipermail/es-discuss/2009-June/009603.html So far discussion has focused on how to dispatch operations, but there is an independent design dimension: exactly what behavior programs should be able to overload. Below I advance some use cases as proposed design goals. A motivating goal is to support defining numeric types that work in most places where primitive numbers work. So if I write classes for Complex and Decimal, it should be possible for me to arrange that: Ordinary arithmetic just works, and mixing Complex numbers with primitive numbers produces a Complex result; Decimal("0.2") * Decimal("0.8") ---> Decimal("0.16") 5 * Complex(0, 1) --> Complex(0, 5) Adding a number to a string invokes toString (ideally it wouldn't require any code to get this behavior; it would be the default even for types that overload + in other cases); Decimal("0.2") + " m/s" ---> "0.2 m/s" "" + Complex(0, 3) ---> "0+3i" The increment/decrement and compound assignment operators just work, if the underlying operator is overloaded (+ and * in these examples); x = Decimal("1"), ++x ---> Decimal("2") Decimal("3")++ ---> ***ReferenceError x = Complex(3, 4); x *= Complex(0, 1) --> Complex(-4, 3) Comparisons work; Decimal("-1.27") <= 0 ---> true 0 < Decimal("-1.27") ---> false Decimal("-1.27") >= Decimal("-1") ---> false Comparisons that don't make sense throw an exception (actually this is *not* how primitive numbers behave, but it seems like desirable behavior, and easy enough to support for authors who want it); Complex(0, 2) < 2 ---> ***Error Complex(0, 2) < Complex(2, 0) ---> ***Error Zero values are false, not true; !Complex(0, 0) ---> true Complex(0, 0) ? "t" : "f" ---> "f" if (x) f(); ---> f is called if x is nonzero User-defined numbers can be == to primitive numbers (but not ===); Decimal("100") == 100 ---> true 100 == Decimal("100") ---> true Complex(100, 0) == 100 ---> true Two numbers with the same value and the same type are equal (and I should not have to e.g. cache the instances and make Complex(5, 3) return the same object every time). Complex(5, 3) == Complex(5, 3) ---> true Complex(5, 3) === Complex(5, 3) ---> true [3, Complex(3, 0)].indexOf(Complex(3, 0)) ---> 1 I expect this bit about === will be contentious, but having indexOf return -1 here would be a real shame, and if there's a hash-map type in ES-next the case gets even stronger. Anyway there seems little use in having === distinguish between objects that nothing else in the language can tell apart. Beyond numbers, there are other important use cases for operator overloading: operator[]. Overloading indexing, even just for integer indices, would be more than welcome. There are some nontrivial design decisions here, because the language interacts with properties in so many ways: obj[i] obj[i] = x delete obj[i] i in obj for (i in obj) ... Object.getOwnPropertyNames(obj) Object.getOwnPropertyDescriptor(obj, i) Object.defineProperty(obj, ...) and I'm sure I left some out. Worst-case, we add a hook for each of them. I suspect only integer indices should be supported in the language, but WebAPI/HTML5 might benefit if ES-next defines some kind of extension point (short of host objects) that can be used to describe the legacy Web APIs that do catchall indexing for arbitrary property names. operator(). SpiderMonkey supports this for host objects of custom classes implemented in C/C++. Python supports it in the language, and the feature is widely used, e.g. in classes that model mathematical functions, in libraries that create wrappers/proxies for objects and their methods, and occasionally just so that some object quacks like a function (that is, it can be passed where a function is wanted, e.g. to an API like addEventListener, without requiring the user to write a lambda every time). It makes sense to support overloading both `F(x)` and `new F(x)` syntax. Several built-in functions behave differently depending on which syntax is used; ES programs might want to do the same. This use case is less important, but easy enough to support, if it's considered worthwhile: Mutable types. Allowing operators to apply to mutable types, and in the case of operators such as += and ++, allowing them to modify an object in place, has some uses. C++ supports this, but the reasons it makes sense in C++ don't really apply to ECMAScript; Python is the only reference-language I know of that supports it, and it is useful for cases where copying would be costly, such as: A *= 2; // double each element of a matrix A += B; // add two large matrices Python uses operators for data structures more than ES currently does, so += is used for extending a list in-place, and |= for adding to a hash-set. In addition I'll suggest a few non-goals: Letting programs define arbitrary sequences of punctuation characters to be operators (for example, ** or ~= or ->). Overloading the comma operator. Separately overloading !x, x&&, x||, x?:, if(x), while(x), etc. (Allowing types to override ToBoolean should be enough.) Overloading instanceof or typeof. Overloading the relational operators to return anything other than a boolean. Overloading == and != separately. (A single "equals()" hook should suffice.) Overloading < <= > >= separately. (A single "compareTo()" hook should suffice.) Oddly enough, almost all of these things I call unnecessary are things several languages do. So clearly this is subject to some discussion to say the least! It would be possible to write a proposal in near-spec-ready language that addresses this kind of question without assuming anything in particular about the dispatch mechanism (the text would refer to a DispatchOperation abstract operation) or the syntax for defining operator overloads. I'd be willing to attempt that, in the interest of having a concrete proposal on the table. Comments are welcome. -j _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss