The right side of a logical double AND (&&) riddle
References:
- https://docs.intersystems.com/iris20243/csp/docbook/DocBook.UI.Page.cls?...
- https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...
- https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...
ObjectScript always follows strict left-to-right execution of arithmetic operators.
The && operator evaluates the left operand and returns a value of FALSE (0) if it evaluates to a value of zero. Only if the left operand is nonzero does the && operator then evaluates the right operand. It returns a value of FALSE (0) if the right operand evaluates to a value of zero. Otherwise it returns a value of TRUE (1).
So here is a riddle then. Given the expression
write (1=0) && (1=0)
ObjectScriptObjectScript
we get the result "0", which is expected. But if we remove the parenthesis we should in theory (to my understanding) should get the same result, but we do not! We instead get "1" for the following
write 1=0 && 1=0
ObjectScriptObjectScript
if this is truly left to right only operational procedence, then shouldn't it still be "0"?
1=0 && 1=0
0 && 1=0
0 (since the left side is 0, the right side shouldn't be evaluated according to docs)
But what appears to be happening is:
1=0 && 1=0
0 && 1=0
0=0
It was not clear that the right side of the `&&` operator does not extend past the "1" but literally checks only "0 && 1" and then continues to check "0=0"
I assumed that anything past a "&&" would be considered the "right side" and would exit early.
We cannot "exit early" from the entire line, because there is more following the && operation.
It may make sense if you realize that
0 && 1 = 0
is the same as:
(0 && 1) = 0
We don't have to check the right side of the && before resolving the parenthetical expression, but that doesn't mean that we shouldn't continue evaluating the rest of the line.
exactly, but that was not clear until I hit this. I assumed "return" meant stop processing the rest of the line. Sort of like this in Javascript, I just assumed returned meant to return, not continue...
// a = b && c = d function foo(a, b, c, d) { let res = a === b ? 1 : 0; // a = b if (res === 0) { // left side of && return res // return left side } res = c // res && c res = res === d ? 1 : 0 // res = d return res }
To help visualize how this is being evaluated, maybe it'll help if we break it down in the order it's being evaluated. An equivalent statement for the strict left-to-right evaluation would be this:
W (((1=0) && 1) = 0) ; nested operations in different text color.
So, to evaluate (1=0) first, 1=0 is false, therefore the result is zero.
That now makes the full equation:
W ((0 && 1) = 0) ;
Now, let's evaluate (0 && 1) -- 0 && 1 equates to zero also.
That now makes the full equation:
W (0 = 0) ; last nested part of the equation;
So, lastly, the result of 0=0 is true, or 1.
I hope this explanation helps!
Great breakdown - just adding that in the terms of the documentation, the "right side" of the && operator in this case is "1". The = sign and everything after it is part of another operation and is not considered in this context.
I think the other commenters clarified it all, but I thought I'd add a little more.
Try this variant, with the variable x intentionally undefined.
write (1=0) && (x = 0)
0
Since 1=0 is 0, you don't get an <UNDEFINED> for x, since the right-hand (x=0) expression is ignored, and the entire statement is 0. Now try this:
write 1=0 && x=0
1
which, as @Roger Merchberger showed, is really
write (((1=0) && x) = 0)
Since 1=0 is 0, you again don't get an <UNDEFINED> for x, since the x expression (only) is ignored, and the ((1=0) && x) expression is 0. Finally, 0=0 is 1.