Loren on the Art of MATLAB

Turn ideas into MATLAB

A Logical Story

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.




Published with MATLAB® 7.3

|
  • print
  • send email

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.