For Gauche 0.9.10

Next: , Previous: , Up: Core syntax   [Contents][Index]

### 4.5 Conditionals

Special Form: if test consequent alternative
Special Form: if test consequent

[R7RS base] Test is evaluated. If it yields a true value, consequent is evaluated. Otherwise, alternative is evaluated. If alternative is not provided, it results undefined value.

```(if (number? 3) 'yes 'no) ⇒ yes
(if (number? #f) 'yes 'no) ⇒ no

(let ((x '(1 . 2)))
(if (pair? x)
(values (car x) (cdr x))
(values #f #f)))
⇒ 1 and 2
```
Special Form: cond clause1 clause2 …

[R7RS+ base][SRFI-61] Each clause must be the form

```(test expr …)
(test => expr)
(test guard => expr)
(else expr expr2 …)
```

The last form can appear only as the last clause.

`cond` evaluates test of each clauses in order, until it yields a true value. Once it yields true, if the clause is the first form, the corresponding exprs are evaluated and the result(s) of last expr is(are) returned; if the clause is the second form, the expr is evaluated and it must yield a procedure that takes one argument. Then the result of test is passed to it, and the result(s) it returns will be returned.

The third form is specified in SRFI-61. In this form, test can yield arbitrary number of values. The result(s) of test is(are) passed to guard; if it returns a true value, expr is applied with an equivalent argument list, and its result(s) is(are) returned. If guard returns `#f`, the evaluation proceeds to the next clause.

If no test yields true, and the last clause is not the fourth form (else clause), an undefined value is returned.

If the last clause is else clause and all tests are failed, exprs in the else clause are evaluated, and its last expr’s result(s) is(are) returned.

```(cond ((> 3 2) 'greater)
((< 3 2) 'less)) ⇒ greater
(cond ((> 3 3) 'greater)
((< 3 3) 'less)
(else 'equal)) ⇒ equal
(cond ((assv 'b '((a 1) (b 2))) => cadr)
(else #f)) ⇒ 2
```
Special Form: case key clause1 clause2 …

[R7RS+ base][SRFI-87] Key may be any expression. Each clause should have the form

```((datum ...) expr expr2 …)
((datum ...) => proc)
```

where each datum is an external representation of some object. All the datums must be distinct. The last clause may be an “else clause,” which has the form

```(else expr expr2 …)
(else => proc)
```

First, key is evaluated and its result is compared against each datum. If the result of evaluating key is equivalent (using `eqv?`, see Equality), to a datum, then the expressions in the corresponding clause are evaluated sequentially, and the result(s) of the last expression in the clause is(are) returned from the case expression. The forms containing `=>` are specified in SRFI-87. In these forms, the result of key is passed to proc, and its result(s) is(are) returned from the case expression.

If the result of evaluating key is different from every datum, then if there is an else clause its expressions are evaluated and the result(s) of the last is(are) the result(s) of the case expression; otherwise the result of the case expression is undefined.

```(case (* 2 3)
((2 3 5 7) 'prime)
((1 4 6 8 9) 'composite)) ⇒ composite

(case (car '(c d))
((a) 'a)
((b) 'b)) ⇒ undefined

(case (car '(c d))
((a e i o u) 'vowel)
((w y) 'semivowel)
(else 'consonant)) ⇒ consonant

(case 6
((2 4 6 8) => (cut + <> 1))
(else => (cut - <> 1))) ⇒ 7

(case 5
((2 4 6 8) => (cut + <> 1))
(else => (cut - <> 1))) ⇒ 4
```
Macro: ecase key clause1 clause2 …

This works exactly like `case`, except when there’s no `else` clause and the value of key expression doesn’t match any of datums provided in clauses. While `case` form returns undefined value for such case, ecase raises an error.

It is taken from Common Lisp. It’s a convenient form when you want to detect when unexpected value is passed just in case.

```(ecase 5 ((1) 'a) ((2 3) 'b) ((4) 'c))
⇒ ERROR: ecase test fell through: got 5, expecting one of (1 2 3 4)
```
Special Form: and test …

[R7RS base] The test 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 test …

[R7RS base] The test 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)
```
Special Form: when test expr1 expr2 …
Special Form: unless test expr1 expr2 …

[R7RS base] Evaluates test. If it yields true value (or false in case of `unless`), expr1 and expr2 … are evaluated sequentially, and the result(s) of the last evaluation is(are) returned. Otherwise, undefined value is returned.

Macro: assume test-expr message …

[SRFI-145] Evaluates text-expr and returns its value.

Also, this form declares the programmer’s intent that the code following this path always satisfy test-expr.

Currently, Gauche always signals an error with message … if text-expr evaluates to `#f`.

```(define (real-sqrt x)
(assume (and (real? x) (>= x 0)))
(sqrt x))

gosh> (real-sqrt -1)
*** ERROR: Invalid assumption: (and (real? x) (>= x 0))
```

Note: This form is advisory—it isn’t guaranteed for an error to be signaled when test-expr fails. For example, we may add an optimization option that omits testing in speed-optimized code in future. We may also enhance the compiler to generate better code using the given information—for example, in the above `real-sqrt` code, the compiler could theoretically deduce that `(sqrt x)` only needs to work as real functions, so it would be able to generate specialized code. Use this form to inform the compiler and the reader your intention.

Macro: assume-type expr type

Evaluates expr, and Checks if the value has type type. If not, raises an error. The result of expr is returned.

As type, you can specify a Gauche class. The value is of type if it satisfies `(is-a? value type)` (see Types and classes).

Note: Like `assume`, this form is advisory; it is not guaranteed that the check is performed, nor expr is evaluated.

On the other hand, the type assumption may be used by the compiler future compilers for optimizations.

Next: , Previous: , Up: Core syntax   [Contents][Index]