Common Lisp the Language, 2nd Edition
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.