Common Lisp the Language, 2nd Edition

Next: Control Structure Up: Predicates Previous: Equality Predicates

# 6.4. Logical Operators

Common Lisp provides three operators on Boolean values: `and`, `or`, and `not`. Of these, `and` and `or` are also control structures because their arguments are evaluated conditionally. The function `not` necessarily examines its single argument, and so is a simple function.

[Function]
`not` `x`

`not` returns `t` if x is `nil`, and otherwise returns `nil`. It therefore inverts its argument considered as a Boolean value.

`null` is the same as `not`; both functions are included for the sake of clarity. As a matter of style, it is customary to use `null` to check whether something is the empty list and to use `not` to invert the sense of a logical value.

[Macro]
`and` `{form}*`

`(and form1 form2 ... )` evaluates each form, one at a time, from left to right. If any form evaluates to `nil`, the value `nil` is immediately returned without evaluating the remaining forms. If every form but the last evaluates to a non-`nil` value, `and` returns whatever the last form returns. Therefore in general `and` can be used both for logical operations, where `nil` stands for false and non-`nil` values stand for true, and as a conditional expression. An example follows.

    (if (and (>= n 0)
             (< n (length a-simple-vector))
             (eq (elt a-simple-vector n) 'foo))
        (princ "Foo!"))

The above expression prints `Foo!` if element `n` of `a-simple-vector` is the symbol `foo`, provided also that `n` is indeed a valid index for `a-simple-vector`. Because `and` guarantees left-to-right testing of its parts, `elt` is not called if `n` is out of range.

To put it another way, the `and` special form does short-circuit Boolean evaluation, like the and then operator in Ada and what in some Pascal-like languages is called cand (for ``conditional and''); the Lisp `and` special form is unlike the Pascal or Ada and operator, which always evaluates both arguments.

In the previous example writing

    (and (>= n 0)
         (< n (length a-simple-vector))
         (eq (elt a-simple-vector n) 'foo)
         (princ "Foo!"))

would accomplish the same thing. The difference is purely stylistic. Some programmers never use expressions containing side effects within `and`, preferring to use `if` or `when` for that purpose.

From the general definition, one can deduce that `(and x)` == x. Also, `(and)` evaluates to `t`, which is an identity for this operation.

One can define `and` in terms of `cond` in this way:

    (and x y z ... w) == (cond ((not x) nil)
    			   ((not y) nil)
    			   ((not z) nil)
    			   ...
    			   (t w))

See `if` and `when`, which are sometimes stylistically more appropriate than `and` for conditional purposes. If it is necessary to test whether a predicate is true of all elements of a list or vector (element 0 and element 1 and element 2 and ...), then the function `every` may be useful.

[Macro]
`or` `{form}*`

`(or form1 form2 ... )` evaluates each form, one at a time, from left to right. If any form other than the last evaluates to something other than `nil`, `or` immediately returns that non-`nil` value without evaluating the remaining forms. If every form but the last evaluates to `nil`, `or` returns whatever evaluation of the last of the forms returns. Therefore in general `or` can be used both for logical operations, where `nil` stands for false and non-`nil` values stand for true, and as a conditional expression.

To put it another way, the `or` special form does short-circuit Boolean evaluation, like the or else operator in Ada and what in some Pascal-like languages is called cor (for ``conditional or''); the Lisp `or` special form is unlike the Pascal or Ada or operator, which always evaluates both arguments.

From the general definition, one can deduce that `(or x)` == x. Also, `(or)` evaluates to `nil`, which is the identity for this operation.

One can define `or` in terms of `cond` in this way:

    (or x y z ... w) == (cond (x) (y) (z) ... (t w))

See `if` and `unless`, which are sometimes stylistically more appropriate than `or` for conditional purposes. If it is necessary to test whether a predicate is true of one or more elements of a list or vector (element 0 or element 1 or element 2 or ...), then the function `some` may be useful.

Next: Control Structure Up: Predicates Previous: Equality Predicates