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.