3. その結果を表示する
3.10 制御構造 ( その 1)
let*は let と似て局所変数を用意します。最初の局所変数の初期値を求めると、その 値を次の局所変数の初期値を求めるときに使うことができる点が、letと違うところです。
例を見てみましょう。
> (define x 1)
#<unspecified>
> (define y 3)
#<unspecified>
> (let* ((x (+ y 1)) (y (* x 2))) (+ x y)) 12
(+ y 1) を評価すると
4
なので、これが x の初期値となります。次は (* x 2)を評価して y の初期値を決めますが 、ここでの xは最初の局所変数が使われます。ですので、yの 初期値は
4
となります。letや let*は入れ子にして使うこともできます。次の式を評価すると、ど ういう結果 が得られるでしょうか
?
(let ((x 0)) (let ((x 1))
x))
答えは 1です。変数は、文面上で一番近い定義による束縛による値が使われますので、(let
((x 1) での定義が使われます。このため、 上の式の評価結果は 1になります。
実行例は次の通りです。
> (foo -1) non-zero
> (foo 0) zero
> (foo 68000) non-zero
このように ifは
} (if h条件式i
h式1
i
h式2i)
の形をしています。h条件式iを評価した結果が真
(
厳密いうと、#f以外)
ならh式1iを評価し 、その値が if の値になります。そうでなければ h式2i を評価し 、その値が if の値 になります。
h式2iのない
4 (if h条件式i
h式i)
の形も使うことができます19。
この場合は h条件式i を評価した結果が真
(
厳密いうと、#f 以外)
ならば h式i を評価し 、その値が ifの値になります。そうでなければ if 返される値は定められていません20。
3.10.2 cond による場合分け
特殊形式 condは、複数の条件式をならべておき、真であるものに対応した式が選ばれ 評価され 、その値が返されます。
次の例を見てください。
(define (score n)
(cond ((<= n 50) 'fail) ((< n 70) 'poor) ((< n 80) 'fair)
(else 'excellent)))
19この形式での使い方は
Scheme
に必須な機能とは定められていません。そのために、処理系によっては この使い方ができない可能性もありますが 、ほとんどの処理系では用意されています。20どのような値が返されるかは処理系に依存します。
この手続き scoreは、 引数nが
50
以下なら failを、
51
以上70
未満なら poorを、
70
以上80
未満なら fairを、
80
以上であれば excellentを返す手続きです。
実行例を見てみましょう
:
> (score 30) fail
> (score 67) poor
> (score 79) fair
> (score 96) excellent
一般に condは、以下の形をしています。
} (cond h節1i
h節2i
...
h節
n
i)つまり condは 、
cond-
節(cond-clause)
と呼ばれる h節i のならびです。それぞれのh節iは (h条件1i h式1i ) の形をしています。
上から順に節の条件部 h条件iが評価され、その結果が真
(
厳密には #f 以外)
ならその節のh式iが評価され 、最後の式の評価結果が cond の値になります。もし述語部が #f であれば次の節に移り、上と同様なことを続けます。
一番最後の節のh条件
n
iには、else を使うこともできます。どの述語も偽であった場 合に、この節の式 h式n
i を評価し 、この最後の式の評価結果を cond の評価結果とし ます。condでは、節が書かれている順番に節の条件部が評価される、ということに十分注意し てください。たとえば 、上の例の節の順番を変えた手続き score2を見てください。
(define (score2 n)
(cond ((< n 80) 'fair)
((< n 70) 'poor) ((<= n 50) 'fail)
(else 'excellent))) では、これを実行してみます。
> (score2 30) fair
テストで
30
点をとってしまったにも関わらず成績は fair になり、上での場合と結果が 違っています。これは最初の節の条件が真なのでこういう結果になりました。3.10.3 begin による式の逐次評価
特殊形式beginは、ならんだ複数の式を順に評価します。beginの評価結果は、最後の
式の評価結果となります。たとえば次のようになります。
> (define x 10)
#<unspecified>
> (define y 3)
#<unspecified>
> (begin (display "10 * 3 = ") (display (* 10 3)) (newline)) 10 * 3 = 30
#<unspecified>
となります。ここで手続きdisplay は、引数を表示する手続きです。また手続きnewline は、カーソル位置を次の行に移す
(
改行する)
手続きです。一般に beginは、
} (begin h式1i
h式2i
...
h式
n
i)の形をしていて、h式1i,h式2i h式
n
iの順番で式が評価されます。そしてh式n
i の評価結果が begin の値として返されます。
このように beginは、その本体にならんでいる式をすべて評価しますが 、最後の式の評 価結果以外は使われません。その本体にならんでいる式の評価結果そのものよりも、
画面にデータを表示する
変数に値を代入する
などをする式を順次実行するために使うのが主な目的です。式の評価で得られる結果の以 外の動作を副作用
(side eect)
といいます。たとえば set! はその式が返す値が目的では なく、変数の値を書き換えるという動作を目的として使っていますし 、手続き displayは 画面への表示を目的として使っています。3.10.4 and と or による式の逐次評価
特殊形式andと orは式のならびを順に評価してゆき、ある条件が成立すると途中で終 了します。
特殊形式andは一般に、
} (and h式1i
h式2i
...
h式
n
i)の形をしています。この特殊形式の実行は次のようにしておこなわれます。まず h式1iを 評価します。もし式の評価結果が真
(
厳密には #f以外)
ならば 、次の式h式2iの評価をおこないます。これを、式の評価結果が偽になるまで続けます。
もし最後のh式
n
iまで評価結果が真ならば 、最後の式の評価結果が andの値として返さ れます。もし途中で評価結果が偽のものがあると、そこで and の実行を終了して、#f が andの値として返されます。例を見てみましょう。
> (define x 10)
#<unspecified>
> (and (number? x) (> x 0) (+ x 1)) 11
この例では(number? x)を評価すると真で、次の (> x 0)の評価結果も真です。最後
に (+ x 1)が評価され、その結果は 11となり、これは偽ではないのでその値が andの値
として返されています。
では別の例を見てみましょう。
> (and (number? x) (> x 100) (+ x 1))
#f
この場合では (> x 100)が偽なので、その時点で andの実行が打ち切られます。そし て #f が andの値なっています。
andが特殊形式であることに注意してください。
(
単に論理積を計算するのではありませ ん。)
もし特殊形式でなくて普通の手続きと同じように、実行の前にすべての引数が評価された場合を考えましょう。上の例で変数xが数ではなくて記号だったら、引数評価のと
き、(+ x 1) の評価をしようとして、記号に
1
を加えることになってエラーになります。特殊形式orは一般に、
} (or h式1i
h式2i
...
h式
n
i)の形をしています。特殊形式or の実行は次のようになります。まず h式1
i を評価します。
もし評価結果が偽#f ならば 、次の式 h式2iを評価します。同様にして、評価結果が偽 #f ならばさらに次の式を評価します。これを評価結果が偽である限り続けてゆきます。もし 最後まで評価結果が偽なら、orの値として偽が返されます。もし途中で評価結果が偽以外 のものがあれば or の実行を終了し 、その評価結果が or の値として返されます。or も単 なる論理和を計算するのではないことに注意しましょう。
例を見てみましょう。
> (define x -20)
#<unspecified>
> (if (or (< x 0) (> x 100)) "x < 0 or 100 < x" "else")
"x < 0 or 100 < x"
変数 x の値は -20なので、この例では (< x 0)が真となり、この値が or の値として返 されます。
> (if (or (= x 0) (> x 0)) "x >= 0" "x < 0")
"x < 0"
この例では、orに現れるどの式も評価結果が偽なのでor の値は#fとなり、ifにより "x
< 0"が返されています。