Counter-intuitive operator precedence

While debugging, I spotted a very counter-intuitive operator precedence evaluation. Question: is it just me, or does the following code seem highly susceptible to bugs. If the code is indeed correct, does it serve as a nice example why we should be cautious about omitting parentheses? A warning would have saved me several hours of debugging...
fn test() -> Bool:
return True

fn main():
let A: SIMD[DType.int32, 1] = 10
let B: SIMD[DType.int32, 1] = 10

if A != B & test(): # assumed operator precedence
print("A: not expected but observed")
else:
print("A: expected but not observed")


if (A != B) & test(): # explicit
print("B: not expected and not observed")
else:
print("B: expected and observed")
fn test() -> Bool:
return True

fn main():
let A: SIMD[DType.int32, 1] = 10
let B: SIMD[DType.int32, 1] = 10

if A != B & test(): # assumed operator precedence
print("A: not expected but observed")
else:
print("A: expected but not observed")


if (A != B) & test(): # explicit
print("B: not expected and not observed")
else:
print("B: expected and observed")
3 Replies
sora
sora9mo ago
It's the same as in Python (ref1, ref2).
Unlike C, all comparison operations in Python have the same priority, which is lower than that of any arithmetic, shifting or bitwise operation.
& is "bitwise and", while I think the one you should have used is the logical and, namely and, so A != B and test()
Henk-Jan Lebbink
Yes, makes perfect sense, and I should have trusted the compiler to prevent an unnecessary jump with the logical operator.
sora
sora9mo ago
Without seeing the generated IR or binary, I won’t be so sure about the branchless-ness of the result, but for very simple cases like this I think the compiler will just fold the _ and test() away.
Want results from more Discord servers?
Add your server