Suggestion: Infix operators/functions
In ECMAScript's current state, infix operators would likely complicate future discussions of operator overloading. Before we tackle these problems, I think it's more convenient to have type annotations first.
As it stands, I'd rather see operator overloading before custom operators.
In order to have decent custom operators, you really have to take into
account the whole grammar, and adding them in a way that's not a blatant
tack on usually involves rethinking the entire grammar. In contrast,
operator overloading only requires a rethink of the primitive object model,
and only analogous to how instanceof
had to change to accommodate
Symbol.hasInstance
.
How would this affect ASI?
a // no semicolon inserted since '+' is an infix operator
+b
a // semicolon inserted since '!' is not an infix operator
!b
but what about
function '!'(a, b) { ... }
// now '!' is both an infix and a prefix operator
a // is a semicolon inserted?
!b
On Fri, Feb 2, 2018 at 10:58 AM, Mike Samuel <mikesamuel at gmail.com> wrote:
How would this affect ASI?
a // no semicolon inserted since '+' is an infix operator +b a // semicolon inserted since '!' is not an infix operator !b
but what about
function '!'(a, b) { ... } // now '!' is both an infix and a prefix operator a // is a semicolon inserted? !b
The relevant portion of the spec is 11.9.1 Rules of Automatic Semicolon Insertion www.ecma-international.org/ecma-262/6.0/#sec-automatic-semicolon-insertion : """ There are three basic rules of semicolon insertion: ...
-
When, as a Script or Module is parsed from left to right, a token (called the offending token) is encountered that is not allowed by any production of the grammar, then a semicolon is automatically inserted before the offending token if one or more of the following conditions is true:
- The offending token is separated from the previous token by at least one LineTerminator.
"""
How would operator precedence work? Would we be restricted to 2-argument functions only?
I don't like the idea of custom operators only because of readability of code - it can be different for different pieces of code, and so I think it is a larger surface area for bugs, so I think it would be a net negative.
However, I do like the idea of allowing e.g. +
to be used intuitively and
consistently (i.e. with a fixed meaning) between certain data types that
are not currently supported, e.g.:
Array + Array (array concatenation) Function + Function (function composition)
People in the C++ community have been using overloaded operators since the 1980's, and I wouldn't say that different semantics for the same operator have been a bad idea at all, given that the operator handles completely different types (that can and should be statically analyzable).
I wouldn't even think that these features are abused in the C++ community: Think vector/matrix operations, for instance. Very expressive stuff.
Depending on the application, it could be nicer for Array + Array to become Array(Array, Array) rather than Array(...Array, ...Array). Depends on your use case. As for function composition, it's a matter of preference if A + B is supposed to mean (...args) => A(B(...args)) or rather (...args) =>
B(A(...args)).
My point is, as long as there is a statically analyzable definition for how operators are supposed to behave for a given set of input types, there's no reason not to give programmers the ability to provide such definitions.
But again, these discussions will be much more relevant if proposals such as this one are discussed for standardization at some point.
Time to put infix operators into TypeScript, first, then?
I'm porting this from the TypeScript issue tracker, original from: Microsoft/TypeScript#2319
Since it's very unlikely that the extension methods will ever be implemented [in a call-site-rewrite manner](Microsoft/TypeScript#9 issuecomment-74302592), please consider adding infix operators to enable writing in functional style similarly to what can be done in Haskell:
Monoids
function '+' (left, right) { return left.concat(right); } [1, 2, 3] '+' [4, 5]; // [1, 2, 3, 4, 5]
Monads
function '>>=' (promise, bind) { return promise.then(bind); } $.get('/get') '>>=' x => $.post('/save', x + 1)
Functors
function '.' (inner, outer) { return function(value: a) : c { return outer(inner(value)) } } function f(x) { } function g(y) { } (f '.' g)(x); // z
Thomas Grainger