Next: , Previous: Quoting, Up: Special Forms


2.7 Conditionals

The behavior of the conditional expressions is determined by whether objects are true or false. The conditional expressions count only #f as false. They count everything else, including #t, pairs, symbols, numbers, strings, vectors, and procedures as true (but see True and False).

In the descriptions that follow, we say that an object has “a true value” or “is true” when the conditional expressions treat it as true, and we say that an object has “a false value” or “is false” when the conditional expressions treat it as false.

— special form: if predicate consequent [alternative]

Predicate, consequent, and alternative are expressions. An if expression is evaluated as follows: first, predicate is evaluated. If it yields a true value, then consequent is evaluated and its value is returned. Otherwise alternative is evaluated and its value is returned. If predicate yields a false value and no alternative is specified, then the result of the expression is unspecified.

An if expression evaluates either consequent or alternative, never both. Programs should not depend on the value of an if expression that has no alternative.

          (if (> 3 2) 'yes 'no)                   =>  yes
          (if (> 2 3) 'yes 'no)                   =>  no
          (if (> 3 2)
              (- 3 2)
              (+ 3 2))                            =>  1
     
— special form: cond clause clause ...

Each clause has this form:

          (predicate expression ...)
     

where predicate is any expression. The last clause may be an else clause, which has the form:

          (else expression expression ...)
     

A cond expression does the following:

  1. Evaluates the predicate expressions of successive clauses in order, until one of the predicates evaluates to a true value.
  2. When a predicate evaluates to a true value, cond evaluates the expressions in the associated clause in left to right order, and returns the result of evaluating the last expression in the clause as the result of the entire cond expression.

    If the selected clause contains only the predicate and no expressions, cond returns the value of the predicate as the result.

  3. If all predicates evaluate to false values, and there is no else clause, the result of the conditional expression is unspecified; if there is an else clause, cond evaluates its expressions (left to right) and returns the value of the last one.
          (cond ((> 3 2) 'greater)
                ((< 3 2) 'less))                  =>  greater
          
          (cond ((> 3 3) 'greater)
                ((< 3 3) 'less)
                (else 'equal))                    =>  equal
     

Normally, programs should not depend on the value of a cond expression that has no else clause. However, some Scheme programmers prefer to write cond expressions in which at least one of the predicates is always true. In this style, the final clause is equivalent to an else clause.

Scheme supports an alternative clause syntax:

          (predicate => recipient)
     

where recipient is an expression. If predicate evaluates to a true value, then recipient is evaluated. Its value must be a procedure of one argument; this procedure is then invoked on the value of the predicate.

          (cond ((assv 'b '((a 1) (b 2))) => cadr)
                (else #f))                        =>  2
     
— special form: case key clause clause ...

Key may be any expression. Each clause has this form:

          ((object ...) expression expression ...)
     

No object is evaluated, and all the objects must be distinct. The last clause may be an else clause, which has the form:

          (else expression expression ...)
     

A case expression does the following:

  1. Evaluates key and compares the result with each object.
  2. If the result of evaluating key is equivalent (in the sense of eqv?; see Equivalence Predicates) to an object, case evaluates the expressions in the corresponding clause from left to right and returns the result of evaluating the last expression in the clause as the result of the case expression.
  3. If the result of evaluating key is different from every object, and if there's an else clause, case evaluates its expressions and returns the result of the last one as the result of the case expression. If there's no else clause, case returns an unspecified result. Programs should not depend on the value of a case expression that has no else clause.

For example,

          (case (* 2 3)
             ((2 3 5 7) 'prime)
             ((1 4 6 8 9) 'composite))            =>  composite
          
          (case (car '(c d))
             ((a) 'a)
             ((b) 'b))                            =>  unspecified
          
          (case (car '(c d))
             ((a e i o u) 'vowel)
             ((w y) 'semivowel)
             (else 'consonant))                   =>  consonant
     
— special form: and expression ...

The expressions are evaluated from left to right, and the value of the first expression that evaluates to a false value is returned. Any remaining expressions are not evaluated. If all the expressions evaluate to true values, the value of the last expression is returned. If there are no expressions then #t is returned.

          (and (= 2 2) (> 2 1))                   =>  #t
          (and (= 2 2) (< 2 1))                   =>  #f
          (and 1 2 'c '(f g))                     =>  (f g)
          (and)                                   =>  #t
     
— special form: or expression ...

The expressions are evaluated from left to right, and the value of the first expression that evaluates to a true value is returned. Any remaining expressions are not evaluated. If all expressions evaluate to false values, the value of the last expression is returned. If there are no expressions then #f is returned.

          (or (= 2 2) (> 2 1))                    =>  #t
          (or (= 2 2) (< 2 1))                    =>  #t
          (or #f #f #f)                           =>  #f
          (or (memq 'b '(a b c)) (/ 3 0))         =>  (b c)