elisp: Combining Conditions

 
 10.3 Constructs for Combining Conditions
 ========================================
 
 This section describes three constructs that are often used together
 with ‘if’ and ‘cond’ to express complicated conditions.  The constructs
 ‘and’ and ‘or’ can also be used individually as kinds of multiple
 conditional constructs.
 
  -- Function: not condition
      This function tests for the falsehood of CONDITION.  It returns ‘t’
      if CONDITION is ‘nil’, and ‘nil’ otherwise.  The function ‘not’ is
      identical to ‘null’, and we recommend using the name ‘null’ if you
      are testing for an empty list.
 
  -- Special Form: and conditions...
      The ‘and’ special form tests whether all the CONDITIONS are true.
      It works by evaluating the CONDITIONS one by one in the order
      written.
 
      If any of the CONDITIONS evaluates to ‘nil’, then the result of the
      ‘and’ must be ‘nil’ regardless of the remaining CONDITIONS; so
      ‘and’ returns ‘nil’ right away, ignoring the remaining CONDITIONS.
 
      If all the CONDITIONS turn out non-‘nil’, then the value of the
      last of them becomes the value of the ‘and’ form.  Just ‘(and)’,
      with no CONDITIONS, returns ‘t’, appropriate because all the
      CONDITIONS turned out non-‘nil’.  (Think about it; which one did
      not?)
 
      Here is an example.  The first condition returns the integer 1,
      which is not ‘nil’.  Similarly, the second condition returns the
      integer 2, which is not ‘nil’.  The third condition is ‘nil’, so
      the remaining condition is never evaluated.
 
           (and (print 1) (print 2) nil (print 3))
                ⊣ 1
                ⊣ 2
           ⇒ nil
 
      Here is a more realistic example of using ‘and’:
 
           (if (and (consp foo) (eq (car foo) 'x))
               (message "foo is a list starting with x"))
 
      Note that ‘(car foo)’ is not executed if ‘(consp foo)’ returns
      ‘nil’, thus avoiding an error.
 
      ‘and’ expressions can also be written using either ‘if’ or ‘cond’.
      Here’s how:
 
           (and ARG1 ARG2 ARG3)
           ≡
           (if ARG1 (if ARG2 ARG3))
           ≡
           (cond (ARG1 (cond (ARG2 ARG3))))
 
  -- Special Form: or conditions...
      The ‘or’ special form tests whether at least one of the CONDITIONS
      is true.  It works by evaluating all the CONDITIONS one by one in
      the order written.
 
      If any of the CONDITIONS evaluates to a non-‘nil’ value, then the
      result of the ‘or’ must be non-‘nil’; so ‘or’ returns right away,
      ignoring the remaining CONDITIONS.  The value it returns is the
      non-‘nil’ value of the condition just evaluated.
 
      If all the CONDITIONS turn out ‘nil’, then the ‘or’ expression
      returns ‘nil’.  Just ‘(or)’, with no CONDITIONS, returns ‘nil’,
      appropriate because all the CONDITIONS turned out ‘nil’.  (Think
      about it; which one did not?)
 
      For example, this expression tests whether ‘x’ is either ‘nil’ or
      the integer zero:
 
           (or (eq x nil) (eq x 0))
 
      Like the ‘and’ construct, ‘or’ can be written in terms of ‘cond’.
      For example:
 
           (or ARG1 ARG2 ARG3)
           ≡
           (cond (ARG1)
                 (ARG2)
                 (ARG3))
 
      You could almost write ‘or’ in terms of ‘if’, but not quite:
 
           (if ARG1 ARG1
             (if ARG2 ARG2
               ARG3))
 
      This is not completely equivalent because it can evaluate ARG1 or
      ARG2 twice.  By contrast, ‘(or ARG1 ARG2 ARG3)’ never evaluates any
      argument more than once.