When you have two decisions back to back (ie, no other operations need to be performed inbetween the two tests), then you can combine the two expressions (of the two decisions) into a single expression, and just express it as one decision. You use a boolean operator to combine the two expressions (into one conditional expression).

For example, let's say that you want to do something only if the variable getInput equals 1 (not 0) and also if the variable gotAWindow equals 1. Here is how you may write those two decisions, not using boolean operators:

IF getInput = 1 THEN DO

   IF gotAWindow = 1 THEN DO

      /* Here you do something. */

   END

END
Notice that there are no other operations inbetween the first test (ie, "Does getInput equal 1?") and the second test (ie, "Does gotAWindow equal 1?"). This is a candidate for combining the expressions into one conditional expression using a boolean operator.

Expressions may be combined with the boolean operators: & (and), | (or) and && (xor). They may also be reversed with the \ (not) operator.

The & operator causes the combined expression to be regarded as true only if all of the individual expressions are true. If any one (or more) of the individual expressions is false, then the combined expression is false.

The | operator causes the combined expression to be regarded as true if one (or more) of the individual expressions is true. Only when all of the individual expressions are false, then the combined expression is false.

The && operator causes the combined expression to be regarded as true when one and only one of the individual expressions is true. If more than one expression is true, or none of the expressions are true, then the combined expression is false.

The \ or ^ operators reverse the result of any expression after it. An expression that REXX normally evaluates as true is changed to false when the \ or ^ operator preceeds it. Similarly, an expression that normally evaluates as false is changed to true when preceded by a \ or ^ operator.

For our above example, we want to do something only if both expressions are true, so we could combine the expressions with a & operator, as so:.

IF getInput = 1 & gotAWindow = 1 THEN DO

   /* Here you do something. */

END
Here's another, self-contained example that uses several decisions containing boolean expressions:
/* Decide what range My_Variable's value is in,
 * and print out that range
 */
SAY "Enter a number"
PULL My_Variable
IF My_Variable > 0 & My_Variable < 10 THEN SAY "1-9"
IF My_Variable \< 10 & My_Variable < 20 THEN SAY "10-19"
IF \ (My_Variable < 20 | My_Variable >= 30) THEN SAY "20-29"
IF My_Variable <= 0 | My_Variable >= 30 THEN SAY "Out of range"
Note that we didn't put ELSE keywords before the second, third, and fourth IF keywords. Therefore, REXX tests the expression of each of those IF conditionals, executing whichever ones happen to be true. (Of course, due to the particular expressions that we've used, only 1 will ever be true for any given value of My_Variable).

The above script may also be written using SELECT.

/* Decide what range My_Variable's value is in,
 * and print out that range
 */
SAY "Enter a number"
PULL My_Variable
SELECT
   WHEN My_Variable > 0 & My_Variable < 10 THEN SAY "1-9"
   WHEN My_Variable \< 10 & My_Variable < 20 THEN SAY "10-19"
   WHEN \ (My_Variable < 20 | My_Variable >= 30) THEN SAY "20-29"
   OTHERWISE SAY "Out of range"
END
Of course, only 1 of the WHEN instructions ever gets executed when this SELECT is executed.

You can combine more than two expressions using boolean operators. And you can even use different operators.

/* Do something only if both gotAWindow and getInput
 * are 1, or the time is 6PM.
 */
IF getInput = 1 & gotAWindow = 1 | TIME('C') = '6:00pm' THEN DO

   /* Here you do something. */

END
Note: If you want to force a certain order to which two expressions get tested first, then put parentheses around the expressions.


Potential problem with boolean operators

In some languages, such as C, when you have an expression containing boolean operators, only part of the expression may need be evaluated in order to determine what to do. But, REXX always evaluates the entire expression. This has implications of which you must be aware.

For example, let's take our very first example, and demonstrate using it with actual data:

getInput = 0
gotAWindow = 'NO'

IF getInput = 1 & gotAWindow = 1 THEN DO

   /* Here you do something. */

END
If you run the above script, you'll get a SYNTAX error about a math operation with a variable whose value isn't a number. That's because gotAWindow's value is "NO" which is not a numeric value, and yet in your conditional expression you test if its value is the number 1.

You may be thinking, "But wait! gotInput is 0, so that conditional expression is already false before gotAWindow is tested. It wouldn't matter even if gotAWindow is 1. That expression is still going to be false." You are correct. Nevertheless, REXX evaluates an entire expression. It does not evaluate an expression only to the point that it can be definitively proven to be false or true.

So you must keep in mind that, if you are going to be combining expressions into a single test, you make sure that it is always safe for all expressions to be evaluated. (ie, Don't combine expressions where it is not safe to evaluate a certain expression when a preceding expression is not true).