## 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.