So why not ||=?
Implementation difficulty vs. rarity and suitability of use.
&& and || use short-circuit evaluation, and therefore do not work like any other binary operator. All of the current compound assignments are a simple case of flagging the operation as an assignment and then handling it as its sub-operation (add, subtract, whatever). At least for assignment to a variable.
Objects are supported through pre-processing and trickery to avoid evaluating the sub-expressions more than once. The expression
this.Combinations[combinator][length] += 1 is effectively broken up into sub-expressions
this.Combinations[combinator],
length,
1. These are converted to postfix tokens which, when evaluated, leave three values on the stack (the object,
length,
1). Then comes the trickery, which is like this:
- After the first two sub-expressions, insert GET-IN-PLACE(2). When executed, this takes the 2 top-most values on the stack (the object and length), retrieves the property's current value, but leaves both values on the stack along with the new value.
- After the third sub-expression, insert ADD(2) and SET(3).
&& and || require more work in both cases, to support short-circuit evaluation. They are essentially
unary postfix operators which perform a conditional jump. If the first operand satisfies the short-circuit condition, it is pushed back onto the stack and the jump is performed. Otherwise, the remainder of the expression is evaluated.
I suppose that
x[y] ||= z should
not be equivalent to
x[y] := x[y] || z:
- x and y should be evaluated only once (as for current compound assignment operators).
- Perhaps the assignment should not be performed if the current value satisfies the short-circuit condition. In other words, x[y] || (x[y] := z).
Also,
||= is not 100% suitable for its apparent purpose, since a defined value of zero will be treated the same as an undefined value. What you really want is a null-coalescing compound assignment.