## Conditionals

`test-expression` `::=` `expression`
`consequent` `::=` `expression`
`alternate` `::=` `expression`

Syntax: `if` ``test-expression`` ``consequent`` ``alternate``

Syntax: `if` ``test-expression`` ``consequent``

> An `if` expression is evaluated as follows: first, `test-expression` is evaluated. If it yields a true value, then `consequent` is evaluated and its values are returned. Otherwise `alternate` is evaluated and its values are returned. If `test` yields `#f` and no `alternate` is specified, then the result of the expression is unspecified.

>     (if (> 3 2) 'yes 'no)          ⇒ yes
>     (if (> 2 3) 'yes 'no)          ⇒ no
>     (if (> 3 2)
>         (- 3 2)
>         (+ 3 2))                   ⇒ 1
>     (if #f #f)                     ⇒ unspecified

> The `consequent` and `alternate` expressions are in tail context if the `if` expression itself is.

Syntax: `cond` ``cond-clause```+`

Syntax: `cond` ``cond-clause```*` `(else` ``expression```…``)`

> `cond-clause` `::=` `(` `test-expression` `body` `)`
> | `(``test` `=>` `expression``)`

> A `cond` expression is evaluated by evaluating the `test-expression`s of successive `cond-clause`s in order until one of them evaluates to a true value. When a `test-expression` evaluates to a true value, then the remaining `expression`s in its `cond-clause` are evaluated in order, and the results of the last `expression` in the `cond-clause` are returned as the results of the entire `cond` expression. If the selected `cond-clause` contains only the `test-expression` and no `expression`s, then the value of the `test-expression` is returned as the result. If the selected `cond-clause` uses the `=>` alternate form, then the `expression` is evaluated. Its value must be a procedure. This procedure should accept one argument; it is called on the value of the `test-expression` and the values returned by this procedure are returned by the `cond` expression.

> If all `test-expression`s evaluate to `#f`, and there is no `else` clause, then the conditional expression returns unspecified values; if there is an `else` clause, then its `expression`s are evaluated, and the values of the last one are returned.

>     (cond ((> 3 2) 'greater)
>           ((< 3 2) 'less))         ⇒ greater

>     (cond ((> 3 3) 'greater)
>           ((< 3 3) 'less)
>           (else 'equal))           ⇒ equal

>     (cond ('(1 2 3) => cadr)
>           (else #f))               ⇒ 2

> For a `cond-clause` of one of the following forms:

>     (test expression*)
>     (else expression expression*)

> the last `expression` is in tail context if the `cond` form itself is. For a `cond clause` of the form:

>     (test => expression)

> the (implied) call to the procedure that results from the evaluation of `expression` is in tail context if the `cond` form itself is.

Syntax: `case` ``case-key`` ``case-clause```+`

Syntax: `case` ``case-key`` ``case-clause```*` ``case-else-clause``

> `case-key` `::=` `expression`
> `case-clause` `::=` `((` `datum`*`)` `expression`+`)`
> | `((` `datum`*`)` `=>` `expression` `)`
> `case-else-clause` `::=` `(else` `expression`+`)`
> | `(else =>` `expression` `)`

> Each `datum` is an external representation of some object. Each `datum` in the entire `case` expression should be distinct.

> A `case` expression is evaluated as follows.

> 1. The `case-key` is evaluated and its result is compared using `eqv?` against the data represented by the `datum`s of each `case-clause` in turn, proceeding in order from left to right through the set of clauses.

> 2. If the result of evaluating `case-key` is equivalent to a datum of a `case-clause`, the corresponding `expression`s are evaluated from left to right and the results of the last expression in the `case-clause` are returned as the results of the `case` expression. Otherwise, the comparison process continues.

> 3. If the result of evaluating `key` is different from every datum in each set, then if there is an `case-else-clause` its expressions are evaluated and the results of the last are the results of the `case` expression; otherwise the result of `case` expression is unspecified.

> If the selected `case-clause` or `case-else-clause` uses the `=>` alternate form, then the `expression` is evaluated. It is an error if its value is not a procedure accepting one argument. This procedure is then called on the value of the `key` and the values returned by this procedure are returned by the `case` expression.

>     (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 => (lambda (x) x)))    ⇒ c

> The last `expression` of a `case clause` is in tail context if the `case` expression itself is.

Syntax: `match` ``match-key`` ``expression`` ``match-clause```+`

> The `match` form is a generalization of `case` using `pattern`s,

> `match-key` `::=` `expression`
> `match-clause` `::=`
> `(` `pattern` [`guard`] `body` `)`

> The `match-key` is evaluated, Then the `match-clause`s are tried in order. The first `match-clause` whose `pattern` matches (and the `guard`, if any, is true), is selected, and the corresponding `body` evaluated. It is an error if no `match-clause` matches.

>     (match value
>       (0 (found-zero))
>       (x #!if (> x 0) (found-positive x))
>       (x #!if (< x 0) (found-negative x))
>       (x::symbol (found-symbol x))
>       (_ (found-other)))

> One `case` feature is not (yet) directly supported by `match`: Matching against a list of values. However, this is easy to simulate using a guard using `memq`, `memv`, or `member`:

>     ;; compare similar example under case
>     (match (car '(c d))
>       (x #!if (memv x '(a e i o u)) ’vowel)
>       (x #!if (memv x '(w y)) ’semivowel)
>       (x x))

Syntax: `and` ``test-expression`` `…`

> If there are no `test-expression`s, `#t` is returned. Otherwise, the `test-expression` are evaluated from left to right until a `test-expression` returns `#f` or the last `test-expression` is reached. In the former case, the `and` expression returns `#f` without evaluating the remaining expressions. In the latter case, the last expression is evaluated and its values are returned.

>     (and (= 2 2) (> 2 1))          ⇒  #t
>     (and (= 2 2) (< 2 1))          ⇒  #f
>     (and 1 2 'c '(f g))            ⇒  (f g)
>     (and)                          ⇒  #t

> The `and` keyword could be defined in terms of `if` using `syntax-rules` as follows:

>     (define-syntax and
>       (syntax-rules ()
>         ((and) #t)
>         ((and test) test)
>         ((and test1 test2 ...)
>          (if test1 (and test2 ...) #t))))

> The last `test-expression` is in tail context if the `and` expression itself is.

Syntax: `or` ``test-expression`` `…`

> If there are no `test-expression`s, `#f` is returned. Otherwise, the `test-expression`s are evaluated from left to right until a `test-expression` returns a true value `val` or the last `test-expression` is reached. In the former case, the `or` expression returns `val` without evaluating the remaining expressions. In the latter case, the last expression is evaluated and its values are returned.

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

> The `or` keyword could be defined in terms of `if` using `syntax-rules` as follows:

>     (define-syntax or
>       (syntax-rules ()
>         ((or) #f)
>         ((or test) test)
>         ((or test1 test2 ...)
>          (let ((x test1))
>            (if x x (or test2 ...))))))

> The last `test-expression` is in tail context if the `or` expression itself is.

Syntax: `when` ``test-expression`` `form...`

> If `test-expression` is true, evaluate each `form` in order, returning the value of the last one.

Syntax: `unless` ``test-expression`` `form...`

> If `test-expression` is false, evaluate each `form` in order, returning the value of the last one.