Suppose we have 3 variables and we need to ASSERT that they can either all be equal to -1 or neither can be equal to -1. I wrote the following code:
x := 1;
y := 1;
z := 1;
ASSERT( (x = -1) = (y = -1) = (z = -1) );
I often write this kind of check, but for two variables. Surprisingly the triple comparison compiled too, but it doesn’t work as expected. For (1, 1, 1) values I expect it to evaluate to true. After substitution of variable values and simplification we get:
ASSERT( False = False = False );
and I thought that it should evaluate to True, but it doesn’t. So how is this triple comparison evaluated?
First of all, the
=operator is a binary operator: it always works on a pair of values. So there’s no such thing as a “triple equality”. The compiler will evaluate one pair, and use the result to evaluate the other.When the compiler sees multiple linked operators, it needs to group them into pairs using what’s called the “precedence of operators”. It’s clear if you think about the basic arithmetic operators we learned in primary school. There’s no doubt what:
3+2*4evaluates to: it’s equivalent to3+(2*4). When in doubt, always add the grouping yourself. If you do that, you see your expression is equivalent to:((False = False) = False), and it’s obvious it evaluates to:(True = False).What you probably want is to use the
ANDoperator and group your initialAssertlike this:ASSERT(((x = -1) = (y = -1)) and ((y = -1) = (z = -1)))Then I’d probably either write that expression on multiple lines to make the
ANDoperator obvious (SQL habit, I know), or rewrite it completely:or this variant:
My rule is: if it takes more then 1 second to figure out the precedence of operators, add parentheses.