Conditionals - MIT/GNU Scheme 9.1
Description: MIT/GNU Scheme 9.1

Next: Sequencing, 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)