すべての言語と同様に、Schemeには条件式があります。
基本フォームはif
です。
(if test-expression then-branch else-branch)
test-expression
が評価されて真(すなわち、#f
以外の値)になれば、
“then”の枝が評価されます。さもなければ、“else”の枝が評価されます。
“else”の枝はなくてもかまいません。
(define p 80) (if (> p 70) 'safe 'unsafe) => safe (if (< p 90) 'low-pressure) ;no ``else'' branch => low-pressure
Schemeでは利便のために他にも条件式フォームが用意されています。
これらはすべて、if
式に展開されるマクロ(chap 8)として
定義することができます。
when
とunless
when
とunless
はひとつの枝(“then”あるいは“else”の枝)しかない
基本条件式が必要なときに便利です。
(when (< (pressure tube) 60) (open-valve tube) (attach floor-pump tube) (depress floor-pump 5) (detach floor-pump tube) (close-valve tube))
tube
のpressure
が60
未満と仮定すると、この条件式は
floor-pump
をtube
に取り付け、5
回押します
(attach
とdepress
はなにか適当な手続きです)。
同じプログラムをif
を使うと次のようになります。
(if (< (pressure tube) 60) (begin (open-valve tube) (attach floor-pump tube) (depress floor-pump 5) (detach floor-pump tube) (close-valve tube)))
when
の枝は暗黙のbegin
であり、一方、if
では
どちらかのブランチに2つ以上フォームがあるときには
明示的なbegin
が必要です。
同じ振舞いをunless
をつかって書けば以下のようになります。
(unless (>= (pressure tube) 60) (open-valve tube) (attach floor-pump tube) (depress floor-pump 5) (detach floor-pump tube) (close-valve tube))
すべてのSchemeがwhen
とunless
を用意しているわけではありません。
おつかいのSchemeになければ、マクロ(8章参照)として定義できます。
cond
cond
フォームは入れ子になったif
式を表現するのに便利です。
最後以外の“else”の枝には新しいif
が導入されます。したがって、
(if (char<? c #\c) -1 (if (char=? c #\c) 0 1))
はcond
をつかって、次のように書けます。
(cond ((char<? c #\c) -1) ((char=? c #\c) 0) (else 1))
このように、cond
はマルチブランチの条件式です。
各節にはテストとそれに結びつくアクションがあります。
最初に成功したテストがそれに結びついたアクションを起します。
最後のelse
節はどのテストも成功しなかった場合に選択されます。
cond
のアクションは暗黙のbegin
です。
case
cond
の特別な場合にはcase
式で圧縮した表現にできます。
これはすべてのテストが所属テストの場合です。
(case c ((#\a) 1) ((#\b) 2) ((#\c) 3) (else 4)) => 3
c
の値を先頭にもつ節が選択されます。
and
とor
Schemeには論理積(“and”)と論理和(“or”)に対応するスペシャルフォームが
用意されています(2.1.1節で見た否定のnot
は手続きです)。
スペシャルフォームand
はすべてのサブフォームが真ならば真を返します。
実際に返ってくる値は最後のサブフォームの値です。サブフォームのひとつでも
偽であれば、and
は#f
を返します。
(and 1 2) => 2 (and #f 1) => #f
スペシャルフォームor
は最初に真になったサブフォームの値を返します。
もし、すべてのサブフォームが偽ならばor
は#f
を返します。
(or 1 2) => 1 (or #f 1) => 1
and
、or
はともにサブフォームを左から右へ評価します。
結果が決りしだい返すことができるのでand
とor
はのこりの
サブフォームを無視することがあります。
(and 1 #f expression-guaranteed-to-cause-error) => #f (or 1 #f expression-guaranteed-to-cause-error) => 1