Schemeの評価と遅延評価
※ 以下はScheme初心者である私の勉強用のメモです。
間違っている可能性がありますので注意してください。
評価と値
評価(evaluate)とは式を実行し、その結果である"値"を返すことである。では、そもそも"値"とはなんだろう?
値とは、"これ以上変形できない計算結果"である。
したがって以下のものは値といえる。
- 数値など
- リストなど
- 関数
- ラムダ式
Schemeの評価
Schemeは適用順評価を採用している。例えば、以下のようなコードを書いた場合を考えると、各部分式を評価した後に関数が呼び出されることが分かる。
例
(define (double x) (* x x)) ; -- 実行 > (double (+ 2 3)) 25
実行順序
- (+ 2 3) が評価され、結果の5が引数として関数doubleに渡される
- (* 5 5) が評価され、25が返る
Schemeの遅延評価
Schemeでは、値が必要になるまで式を評価をしないようにすることが出来る。
これを遅延評価(lazy evaluation)という。
遅延評価を行うには、大きく分けて2通りのやり方がある。
- 0引数のlambda式を使用する(thunk)
- delay式, force式を使用する
lambda式を使用する
上でも述べたようにlambda式の内部は引数が与えられるまで実行されない。そこでこれを利用して、評価の遅延を行うために0引数のlambda式を用いることができる。
例
(define (show-thunk x) (display x) ; <- この時点では評価されない (x) ;<- この時点で評価される(0引数の関数呼出しは括弧で囲む) ) ; -- 実行結果 > (show-thunk (lambda () (+ 2 3))) #<procedure>5
delay式, force式を使用する
lambda式を利用しなくても、R5RSには遅延評価を行うための関数が用意されている。
delay式
遅延評価を行うにはdelay式を使用する。
一般形
(delay 引数)
delay式を実行すると、引数はpromiseと呼ばれる状態になる。
force式
delay式でpromise状態にしたオブジェクトを評価する。
一般形
(force 引数)
例
(define (show-delay x) (display x) ; <- この時点では評価されない (force x) ;<- この時点で評価される ) ; -- 実行結果 > (show-delay (delay (+ 2 3))) #<struct:promise>5