Let me set the stage for today's blog. Logical variables have been part of MATLAB from the early days. They are particularly useful in constructs involved flow-of-control, such as if and while statements. But MATLAB, being an array-oriented language, needs to deal with expressions following if and while that might be any size, including empty matrices. But sometimes users get confused when two statements, seemingly the same, behave differently. The understanding lies in the intersection of scalar expansion, empty arrays, and logical operators, both short-circuit and elementwise.
Contents
Logical Operators, Scalar Expansion, and Empty Arrays
Recently on the MATLAB newsgroup, a user wondered why two statements, that seemed the same, didn't give the same answer. Let's take a look.
if 4 | [] disp('Must be true') end
Must be true
MATLAB evaluates
4 | []
as true.
However, swapping the order of the argument to | results in a false.
if [] | 4 disp('Must be true') else disp('Must be false') end
Must be false
How can that be?
Information to Help Unravel the Mystery
There are several concepts that might be helpful for understanding this mystery.
- Empty arrays evaluate to false for the purposes of if and while.
- The nonscalar | and & operators short-circuit in if and while expressions, but not otherwise.
- It's best to feed if and while scalar expressions. This means considering using the newer (MATLAB version 6.5) logical operators || and &&. These operators always short-circuit.
- Use reduction operations explicitly to reduce expressions to scalar. Examples of these operations include all and any.
Back to the Example
So, what's happening with this code?
if 4 | [] disp('Must be true') end % The 4 is nonzero and is unequivocally true, so that's the result you see.
Must be true
Inverting the statement requires evaluation of the [] first, then a scalar expansion occurs with the 4, yielding [] and that is false.
if [] | 4 disp('Must be true') else disp('Must be false') end
Must be false
If you were trying to debug this, however, you'd be tempted to evaluate
dbg = 4 | []
dbg =
[]
You would find dbg is empty (because of scalar expansion) and therefore, would be false according to most of the rules above. However, it does not account for the short-circuit nature of | and & in the if and while.
Notes and Recommendations
If you might have empties that you want to check for, check out isempty.
Use the || and && operators in expressions destined for if and while. These expressions behave consistently, meaning they always short-circuit, and are therefore easier to debug. They also force you to reduce your expression to a scalar and it is easier to see what a simple true or false means in the context of the flow-of-control. Do you have any other guidelines? Share them here.
Get
the MATLAB code
Published with MATLAB® 7.3



There must be some performance benefit to justify, “The nonscalar | and & operators short-circuit in if and while expressions, but not otherwise.” Can you give some examples of this benefit?
Before this week’s column, I would have thought that the purpose of the operation was return a true if either of the arguments existed. Thus, MatLab doesn’t operate as I expect, which is a flaw and should be corrected.
Because of the flaw, I have to add complexity to the code, something like this:
if ~isempty([]) | ~isempty(4)
disp(’Must be true’)
else
disp(’Must be false’)
end
if ~isempty(4) | ~isempty([])
disp(’Must be true’)
else
disp(’Must be false’)
end
Now I get the expected result.
How can you have ‘if’ shortcut ‘|’ with something that is false?
In my (rapidly made up) opinion this is a severe bug. Lets compare:
if 0 | 4
disp(’Must be true’)
else
disp(’Must be false’)
end
Displays:
Must be true
As it should, since | is true since 4 is true. No shortcut in this case.
Wouldn’t the defintion of ’short-circuit’ (with respect to ‘if’ or ‘while’) be to stop evaluating arguments to an ‘or’ or ‘and’ operator as soon as the final result of the operation can be definitively determined? Therefore, an ‘or’ operator (|) should continue evaluating arguments until
1) it comes to the first TRUE argument, or
2) it has evaluated ALL of the arguments as false.
Similarly, I would expect an ‘and’ operator (&) to continue evaluating arguments until
1) it comes to the first FALSE argument, or
2) it has evaluated ALL of the arguments as true.
In the first example (’if 4 | []’), the ‘or’ operator short-circuits after evaluating 4 as a true argument. In the second example (’if [] | 4′), why should ‘or’ stop evaluating? The first argument is false, as you’ve explained: “Empty arrays evaluate to false for the purposes of if and while.” The ‘or’ operator should then continue to evaluate as it has not yet determined whether the remaining arguments are true or false.
All-
I didn’t explain this well, I think. What happens is that
[] | 4 does a scalar expansion, ends up [] and therefore evaluates to false. So it’s not the short-circuit that causes the answer, but the scalar expansion. I will update the article to indicate this.
–Loren
If it is a scalar expansion, why does that not take place in the first example, ‘if 4 | []’? Are the two cases treated differently with respect to operator priority? What are the rules for the priority of evaluating the operators in an ‘if’ or ‘while’ statement? Why would they differ in the two examples?
Ed-
The reason the 2nd one doesn’t need to do scalar expansion is because it is true itself before doing the next evaluation
( xxx | [] ) since 4 is nonzero. The short-circuiting happens as soon as truth can be determined.
This was meant to demonstrate that you are MUCH safer using || and && and reducing your expressions to scalar values yourself. Your code will more likely be readable later and do as you expect. Using the arrays versions, | and &, lead to weirdness, especially when empty arrays might be around.
–Loren
Ahhhh. Thanks for clarifying! I understand more clearly now.