Case analysis can be implemented with the conditional expressions cond, case and if. Also the logical expressions and, or and not can be used.
The syntax of if is as follows:
(if condition consequent alternative)or
(if condition consequent)If the condition is true, then the value of consequent is returned, otherwise the alternative is returned. If no alternative is given and the condition is false, the return value will be unspecified.
The usage of cond and if can best be explained with some examples. Let's say we wish to write a procedure that takes two arguments and returns the square of the smaller argument. There are several ways of doing this, but let us use an if expression to accomplish our task.
(define minsquare
(lambda (a b)
(if (< a b)
(square a)
(square b))))
minsquare is called with two arguments, for example
>(minsquare 4 5) 16First we check if 4 is smaller than 5, which it is. Hence, the value of (square a) is returned.
In some cases it is better to use a logical expression instead of if or cond expressions. Procedures written using logical expressions can usually be written in a clearer and more compact way. Let us define a procedure for finding out if three given points form a sawtooth. We will write three versions of the procedure. The first one uses if, the second one uses cond and the third one uses logical expressions.
(define sawtooth?
(lambda (x1 x2 x3)
(if (< x1 x2)
(> x2 x3)
(if (> x1 x2)
(< x2 x3)
#f))))
(define sawtooth?
(lambda (x1 x2 x3)
(cond ((< x1 x2) (> x2 x3))
((> x1 x2) (< x2 x3))
(else #f))))
(define sawtooth?
(lambda (x1 x2 x3)
(or (and (< x1 x2) (> x2 x3))
(and (> x1 x2) (< x2 x3)))))
The cond expression has the following syntax:
(cond (condition1 consequent1)
(condition2 consequent2)
.
.
.
(else alternative))
The conditional expressions are evaluated one at a time until one evaluates to true, in which case the corresponding consequent is evaluated and returned as the value of the whole cond expression. If all conditions are false, the cond expression will have the value of the alternative specified in the else clause. The else clause is optional, but if it is left out and all the conditions are false, the return value will be unspecified.
For example, let's write a procedure that takes three arguments and returns the sum of the two smallest arguments. We will write the procedure using cond expressions:
(define sum-of-smallest
(lambda (x y z)
(cond ((or (and (<= x y) (<= y z))
(and (<= y x) (<= x z)))
(+ x y))
((or (and (<= x z) (<= z y))
(and (<= z x) (<= x y)))
(+ x z))
(else (+ y z)))))
To see how it works, let's try with a few examples:
> (sum-of-smallest 1 2 3) 3 > (sum-of-smallest 3 3 3) 6 > (sum-of-smallest 10 5 7) 12
The case expression is a derived expression and has the following syntax:
(case key clause1 clause2 ...)
The key may be any expression and the clause should have the following form:
((datum1 ...) expression1 expression2 ...)
Each datum is an external representation of a Scheme object and they must all be distinct. The last clause may be an else clause of the form:
(else expr1 expr2 ...)
First key is evaluated and the result is compared against each datum. If the result is equivalent according to eqv? then the expressions in the corresponding clause are evaluated from left to right and the result of the last expression in the clause is returned as the result of the case expression. If no datum is equivalent to the key, the expressions of the else clause will be evaluated and returned as the value of the case expression. If there is neither a datum equivalent to the key nor an else clause, the return value is unspecified.
For example:
> (case (+ 3 4)
((7) 'seven)
((2) 'two)
(else 'nothing))
seven
> (case 'a
((a b c d) 'first)
((e f g h) 'second)
(else 'rest))
first