[ 目次, 前節, 次節, 索引 ]

4.2.1 正規順序と作用的順序



1.1節で評価のモデルの議論を始めた時, Schemeは作用的順序(applicative order)の言語であるといった. つまりScheme手続きへの引数は, 手続きを作用する時にすべて評価する. 反対に正規順序(normal order)の言語では, 実際に引数の値が必要になるまで手続き引数の評価は遅らせる. 手続き引数の評価をぎりぎり最後まで(例えば基本演算が必要とするまで)遅らせることを 遅延評価(lazy evaluation)という.32 手続き
(define (try a b)
  (if (= a 0) 1 b))
を考えよう. (try 0 (/ 1 0))の評価はSchemeではエラーになる. 遅延評価ではエラーにならない. 引数(/ 1 0)は決して評価されず, 評価は1を返す.

   遅延評価を利用する一つの例は, 手続きunlessの定義である.

(define (unless condition usual-value exceptional-value)
  (if condition exceptional-value usual-value))
(unless (= b 0)
        (/ a b)
        (begin (display "exception: returning 0")
               0))
のような式で使うことが出来る. 通常の値と例外の値の両方がunlessが呼び出される前に評価されるので, 作用的順序の言語では使うことが出来ない(問題1.6と比較せよ). 遅延評価の利点は, unlessのようなある種の手続きに, 引数の評価でエラーになったり, 停止しないものがあっても, 有用な計算が出来ることである.

   引数が評価される前に手続きの本体に入る時, その手続きはその引数について ノンストリクト(non-strict)であるという. 手続きの本体に入る前に引数が評価される時, その手続きはその引数について ストリクト(strict)であるという. 33 純粋に作用的順序の言語では, すべての手続きは各引数につき, ストリクトである. 純粋に正規的順序の言語では, すべての合成手続きは各引数につきノンストリクトであり, 基本手続きはストリクトかノンストリクトかのいずれかである. また言語によっては(問題4.31参照)自分で定義した手続きのストリクトさにつき, 細かい制御をプログラマに与えるものもある.

   ノンストリクトにするのが有用な手続きの劇的な例はcons(あるいは一般にデータ構造の構成子の殆んど)である. 要素の値が分らなくても, 要素を組み合せてデータ構造を作り, 結果のデータ構造に演算して有用な計算をすることが出来る. 例えばリストの中の個々の要素の値を知らずとも, リストの長さを計算するというのは十分意味あることである. この考えは4.2.3節で使い, 3章のストリームをノンストリクトなconsの対で作ったリストとして実装する.

問題 4.25


(通常の作用的順序のSchemeで)unlessを上に示したように定義したとし, factorialunlessを使って

(define (factorial n)
  (unless (= n 1)
          (* n (factorial (- n 1)))
          1))
と定義したとする. (factorial 5)を評価しようとすると何が起きるか. われわれの定義は正規順序の言語では動くだろうか.

問題 4.26


Ben BitdiddleとAlyssa P. Hackerはunlessのようなものの実装での遅延評価の重要さにつき, 意見が分れた. Benはunlessは作用的順序では特殊形式で実装出来るという. Alyssaは, 誰かがそうすると, unlessは高水準手続きと一緒に使える手続きではなく, 単なる構文だと反論する. 両者の議論の細部をつめよ. unlessを(condletのように)導出された式としてどう実装するかを示し, unlessが特殊形式としてではなく, 手続きとして使えると有用である状況の例を述べよ.



32 「遅延」の用語と「正規順序」の用語の違いは曖昧である. 一般に「遅延」は特定の評価器の機構を指し, 「正規順序」は特定の評価戦略とは無関係に, 言語の意味論を指す. しかしこれも不動の区別ではなく, 二つの用語はよく取り替えて使われる.

33 「ストリクト」と「ノンストリクト」の用語は本質的に「作用的順序」と「正規順序」と同じ意味であるが, この用語は言語全体に関してではなく, 個々の手続きと引数について述べる点が違う. プログラム言語の学会で誰かが「正規順序の言語 Hassleにはいくつかのストリクトな基本手続きがある, その他の手続きはその引数を遅延評価でとる」と発言するのを聞くかも知れない.

[ 目次, 前節, 次節, 索引 ]