Reason for the existence of non-short-circuit logical operators
Updated answer:
Apologies, I missed the word "logical" in your question even though it is there. (I've taken the liberty of emphasizing it a bit with an edit.)
Consider the case where you want any side-effects to always occur, regardless of whether the left-hand expression evaluates true
or false
. E.g., contrast:
if (foo() & bar()) {
// Only call this if both operations returned true
}
with
if (foo() && bar()) {
// Only call this if both operations returned true
}
Let's assume both foo
and bar
have effects that we want to have happen regardless of whether foo
returns true
or false
. In the first one above, I know that bar
will always get called and have its effect. In the latter, of course, bar
may or may not get called. If we didn't have the non-short-circuit version, we'd have to use temporary variables:
boolean fooResult, barResult;
fooResult = foo();
barResult = bar();
if (fooResult && barResult) {
// ...
}
You might argue (I probably would) that you should do that anyway, because it's way too easy to misread if (foo() & bar())
, but there we go, a pragmatic reason for having non-short-circuit versions.
Original answer:
How would you propose &
(or |
) be a short-circuited operator? With &&
and ||
, it makes sense because you're dealing with boolean conditions: They can be true or false, there are no shades of grey. But &
and |
deal with bits, not booleans. The result is a number. I mean, I guess &
could not evaluate the right-hand side if the left-hand side were 0
, and similarly |
could not evaluate it if the left-hand side were all-bits-on for whatever the type was, but I don't see much point to making the one edge case of each operator significant (as compared to the 254 or more other cases).
There are instances where the components of a boolean expression involve operations that you'd want to have executed in all cases. Consider the following example of checking a password for validity:
while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) {
// re-prompt
}
If the second condition was not evaluated due to short-circuiting, attempts
would never be incremented. Thus greater programmer flexibility is enabled.
My case (C++):
void setFields(Parameters bundle)
{
if (setIfDifferent(&field1, bundle.value1) |
setIfDifferent(&field2, bundle.value2) |
setIfDifferent(&field3, bundle.value3)) {
storeState();
}
}
setIfDifferent() sets the object's field with new value if they differ, in which case it returns true; or it returns false in case the field's and the new value are the same. So, we want to try to set all fields, and if any of them changed, then we want to store new object's state.
You can have some side-effects in logical expression, for example you can assign simultaneously with checking. This may work wrongly if only one part evaluated.
Can't remember good example now, but remember that I was in need of "non-short-circuit" operators sometimes.
Hmmm.... Below is WRONG example, which won't work without "non-short-circuit" OR:
if( (object1=getInstance1()).getNumber() == 1 || (object2=getInstance2()).getNumber() == 2 ) {
// do something which requires bot object1 and object2 assigned
}