佇電腦程式中,通常愛算一个運算式 ê 結果,會 kā 逐个部份照算 ê 次序一改算予清,這種趁早算出來 ê 算法,號做「嚴格計算」 (strict evaluation; eager evaluation)。比論講:
(*2 (+3 (/52)))
1 Strict evaluation ê 作法,會代先共 (/ 5 2) 算出來,得著 2.5,了後 kā 這个結果下 kah (+ 3 ?) ê ?,上尾共 (+ 3 (/ 5 2)) 下佇 (* 2 ?) ê ?,一改 tiō 知結果,見若有愛算 ê 所在,攏 buē-tàng 暫時 mài 算。
但是,有時仔咱無愛共運算 ê 結果做一改執行,tio̍h 共一部份先放 tī 邊仔,需要 ê 時 tsiah 執行,按呢叫做「貧惰計算」(延遲計算,lazy evaluation)。
Tī 介紹貧惰計算使用 ê 所在,咱代先看 Scheme ê 有關語法。通常 Scheme ê 逐个函數,kap Haskell 無仝,攏是嚴格計算 ê。Beh 予計算式「貧惰」,著用 (delay 計算式),按呢 tiō 會產出 promise(欲算 ê 物件)。kàu 欲算 promise ê 時陣著用 (force promise)。以下是舉例,所有 ê 例攏佇 Racket ê Scheme R5RS 環境執行:
> (define a (delay (+21))) ; Tī 終端機輸入,kā (+ 2 1) ê promise 下佇 a > a #<promise> ; a 是 promise > (force a) 3; 逼 a 算出來,得著 3 >
; 提第 n 項(對 0 開始)ê 數值 ; (inf-series-ref 3) -> 8 (define (inf-series-ref n) (inf-series-ref-iter n (inf-series (expt20))) )
; 協助 inf-series-ref ê 函數 (define (inf-series-ref-iter i inf-series-part) (if (= i 0) ; 若是 i == 0,提數列已經算 ê 尾兩項(含 promise, ; tiō 是 inf-series-part)ê 頭,有咱愛 ê 結果。 (car inf-series-part) ; 若是 n != 0,閣用 force 拆開 promise,得著新 ê 一項。 (inf-series-ref-iter (- i 1) (force (cadr inf-series-part)))))
; 協助 inf-series-head ê 函數。 (define (inf-series-head-iter i inf-series-part prev-result) ; 定義可能 ê 結果 (let ((result (append prev-result `(,(car inf-series-part))))) (if (= i 0) result ; i == 0 ê 時,得著結果 (inf-series-head-iter (- i 1) (force (cadr inf-series-part)) result))))
欲做這真簡單,delay tiō 是 kā 函數用無任何引數 ê lambda 包起來。force tiō 是 kā 予 lambda 包起來 ê 執行。毋過準若用 define 定義,因為會代先嚴格計算 beh khah 慢算 ê 表達式,致 kàu 無合咱所愛 ê,所以定著愛用 macro ê 方式來寫:
* [(Scheme) 17. Lazy evaluation](http://www.shido.info/lisp/scheme_lazy_e.html) of Yet Another Scheme Tutorial by Takafumi Shido
* [21. Delayed evaluation and infinite lists in Scheme](http://people.cs.aau.dk/~normark/prog3-03/html/notes/eval-order_themes-delay-stream-section.html) of Functional Programming in Scheme : With Web Programming Examples by Kurt Nørmark, Department of Computer Science, Aalborg University, Denmark
註腳
1 這是 Scheme ê 寫法,共算數符號抑是函數 ê 名 khǹg 頭前,一般是 2 * (3 + 5 / 4)