I was posed a question recently as to why the C++ expression true == true == true
compiled successfully. The person asking was sure that equality comparison held no associativity and that the expression was thus too ambiguous to be well-formed.
Well, in Ruby, this is the case:
-
Subtraction is left associative;
soa - b - 3
acts like(a - b) - 3
. -
Assignment is right associative;
soa = b = 3
acts likea = (b = 3)
. -
Equality is not associative;
soa == b == 3
raisesSyntaxError
.
In fact, C++'s equality operator is left associative, and my immediate thought was that Ruby's behaviour was a little odd.
However, on further thought, I realised that it makes quite a bit of sense.
For example, it essentially prevents the following mistake:
int x = 0, y = 0, z = 0;
std::cout << (x == y == z); // false
Naively, especially when coming directly from a mathematics background, one might expect the output of this program to be true
because all three operands are equal.
But in fact, C++'s comparison takes only two operands, and when implicit associativity is applied explicitly with parentheses, the program's true behaviour becomes more obvious:
int x = 0, y = 0, z = 0;
std::cout << ((x == y) == z);
// true == 0
// false
Ruby's position of completely disallowing such a form in its arithmetic expressions will prevent any such "bugs". Perhaps it would have been better had C++ adopted this position as well.