Previous Page
Next Page

4.16. Low-Precedence Operators

Don't mix high- and low-precedence booleans.

Perl's low-precedence logical not reads much better than its corresponding high-precedence ! operator. So it's tempting to write:

    next CLIENT if not $finished;    # Much nicer than: if !$finished

However, the extremely low precedence of not can lead to problems if that condition is later extended:

    next CLIENT if not $finished || $result < $MIN_ACCEPTABLE;

It's likely that at least some readers of your code will mistake the behaviour of that statement and assume that it's equivalent to:

    next CLIENT if (not $finished) || $result < $MIN_ACCEPTABLE;

It's not. It actually means:

    next CLIENT if not( $finished || $result < $MIN_ACCEPTABLE );

Even if the choice of || was deliberate, and implements the desired test correctly, there is nothing in the code to indicate that the mixing of precedence was intentional. So, while the novice reader is left to wonder about the meaning of the expression, the more experienced reader is left to wonder about its correctness.

Replacing the || with an or would solve the precedence problem (if indeed there were one), since or is even lower precedence than not:

    next CLIENT if not $finished or $result < $MIN_ACCEPTABLE;

And then adding a pair of parentheses would explicitly indicate whether the intention was:

    next CLIENT if not($finished or $result < $MIN_ACCEPTABLE);

or:

    next CLIENT if not($finished) or $result < $MIN_ACCEPTABLE;

On the other hand, the high-precedence boolean operators don't seem to invoke the same levels of fear, uncertainty, or doubt, probably because they're used much more frequently. It's safer and more comprehensible to use only high-precedence booleans in conditional expressions:


    next CLIENT if !$finished || $result < $MIN_ACCEPTABLE;

and then use parentheses when you need to vary precedence:


    next CLIENT if !( $finished || $result < $MIN_ACCEPTABLE);

To maximize the comprehensibility of conditional tests, avoid and and not completely, and reserve low-precedence or for specifying "fallback positions" on fallible builtins:


    open my $source, '<', $source_file
        or croak "Couldn't access source code: $OS_ERROR";

(but see also "Builtin Failures" in Chapter 13).

    Previous Page
    Next Page