Like all languages, Scheme provides
conditionals. The basic form is the if
:
(if test-expression then-branch else-branch)
If test‑expression
evaluates to true (i.e., any value
other than #f
), the “then” branch is evaluated.
If not, the “else” branch is evaluated. The
“else” branch is optional.
(define p 80) (if (> p 70) 'safe 'unsafe) => safe (if (< p 90) 'low-pressure) ;no “else” branch => low-pressure
Scheme provides some other conditional forms for
convenience. They can all be defined as macros
(chapter 8) that expand
into if
-expressions.
when
and unless
when
and unless
are convenient conditionals
to use when only one branch (the “then” or the
“else” branch) of the basic conditional is needed.
(when (< (pressure tube) 60) (open-valve tube) (attach floor-pump tube) (depress floor-pump 5) (detach floor-pump tube) (close-valve tube))
Assuming pressure
of tube
is less than
60
, this conditional will attach floor‑pump
to
tube
and depress
it 5
times. (attach
and depress
are some suitable procedures.)
The same program using if
would be:
(if (< (pressure tube) 60) (begin (open-valve tube) (attach floor-pump tube) (depress floor-pump 5) (detach floor-pump tube) (close-valve tube)))
Note that when
’s branch is an implicit begin
,
whereas if
requires an explicit begin
if either
of its branches has more than one form.
The same behavior can be written using unless
as
follows:
(unless (>= (pressure tube) 60) (open-valve tube) (attach floor-pump tube) (depress floor-pump 5) (detach floor-pump tube) (close-valve tube))
Not all Schemes provide when
and unless
.
If your Scheme does not have them, you can
define them as macros (see chapter 8).
cond
The cond
form is convenient for expressing nested
if
-expressions, where each “else” branch but the last
introduces a new if
. Thus, the form
(if (char<? c #\c) -1 (if (char=? c #\c) 0 1))
can be rewritten using cond
as:
(cond ((char<? c #\c) -1) ((char=? c #\c) 0) (else 1))
The cond
is thus a multi-branch conditional. Each
clause has a test and an associated action. The first
test that succeeds triggers its associated action. The
final else
clause is chosen if no other test
succeeded.
The cond
actions are implicit begin
s.
case
A special case of the cond
can be compressed into a
case
expression. This is when every test is a
membership test.
(case c ((#\a) 1) ((#\b) 2) ((#\c) 3) (else 4)) => 3
The clause whose head contains the value of c
is chosen.
and
and or
Scheme provides special forms for boolean conjunction
(“and”) and disjunction (“or”). (We have already
seen (section 2.1.1) Scheme’s boolean negation
not
, which is a
procedure.)
The special form
and
returns a true value if all its subforms are true. The
actual value returned is the value of the final
subform. If any of the subforms are false, and
returns #f
.
(and 1 2) => 2 (and #f 1) => #f
The special form or
returns the value of its
first true subform. If all the subforms are false,
or
returns #f
.
(or 1 2) => 1 (or #f 1) => 1
Both and
and or
evaluate their subforms
left-to-right. As soon as the result can be
determined, and
and or
will ignore the
remaining subforms.
(and 1 #f expression-guaranteed-to-cause-error) => #f (or 1 #f expression-guaranteed-to-cause-error) => 1