Friday, November 30, 2018

[upqphxne] No associativity for non-associative operators

Consider providing in a programming language a feature in which the programmer can optionally disable acceptability of expressions that use subtraction or division twice or more in a row, for example a - b - c - d or a/b/c/d, because they are potentially confusing because you might forget that the operations must be performed left to right.  Tricky formatting could induce confusion:

/* this is actually equal to 1/4 */
one=1/2
     /
    1/2;

The programmer must explicitly parenthesize: ((a - b) - c) - d, ((a/b)/c)/d, or a - (b + c + d), a/(b*c*d), or a + (-b) + (-c) + (-d), a * (1/b) * (1/c) * (1/d).

Multiple additions or multiplications in a row are not confusing (and therefore remain acceptable) because those operations are associative (ignoring issues like precision loss and overflow).

Other operators we may want to disable their use in series: a <= b <= c, a == b == c, because those expressions don't mean what they mean in mathematics.  (These expressions even pass strict type-checking if the variables are of boolean type.)  The remainder operator (mod): a%b%c.  Exponentiation a^b^c because people often forget it is right associative.

We probably don't want to disable the use of all non-associative operators in series.  Here are some we likely want to keep: list construction (:) and function application ($) in Haskell.  (Previously on expressions of this form: syntactic fold.)  (Incidentally, function composition (.) is associative.)  Stream input (>>) and output (<<) in C++.  However, we may want to disable the same C++ operators when used in series in arithmetic expressions, e.g., 1 << 1 << 3, for the same reason as doing so for subtraction and division: it's potentially confusing.  Left shift feels similar to exponentiation, but it is left associative.

No comments :