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