Triple equality expression evaluation
Asked Answered
D

2

5

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?

Dunlap answered 1/7, 2011 at 9:25 Comment(4)
Neither? How is that possible with 3 conditions?Nationality
+1 for the weirdness of the expression! If you had anything other then boolean values you'd get a Incompatible types compiler error; And I'd guess this is a corner-case since BOOLEAN values are rarely compared with the = operator.Boyhood
Nothing is weird, False = False equals to True, and True <> FalseOpportunism
(Weired != Unexplained) and (Weired ~= bizarre ~= unusual).Boyhood
B
8

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*4 evaluates to: it's equivalent to 3+(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 AND operator and group your initial Assert like 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 AND operator obvious (SQL habit, I know), or rewrite it completely:

Assert (
  ((x = -1) = (y = -1))
  and
  ((x = -1) = (z = -1))
);

or this variant:

Assert (
  ((x = -1) and (y = -1) and (z = -1))
  or
  ((x <> -1) and (y <> -1) and (z <> -1))
);

My rule is: if it takes more then 1 second to figure out the precedence of operators, add parentheses.

Boyhood answered 1/7, 2011 at 9:30 Comment(0)
L
2

Comparison is associative: False=False=False is equivalent to (False=False)=False. The first False=False evaluates to True, leading to comparison True=False which in turn is False.

Limb answered 1/7, 2011 at 9:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.