Scheme ê 延遲計算 (lazy evaluation) ê 例
(上尾更新 tī:2019-01-20)
介紹
佇電腦程式中,通常愛算一个
(* 2 (+ 3 (/ 5 2))) |
1
Strict evaluation ê 作法,會代先共 (/ 5 2) 算出來,得著 2.5,了後 kā 這个結果下 kah (+ 3 ?) ê ?,上尾共 (+ 3 (/ 5 2)) 下佇 (* 2 ?) ê ?,一改 tiō 知結果,
但是,有時仔咱無愛共運算 ê 結果做一改執行,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 (+ 2 1))) ; Tī 終端機輸入,kā (+ 2 1) ê promise 下佇 a |
咱無法度共 promise kap 數值用 +、-、*、/ 直接算:
> (+ (- 12 6) (delay (+ 2 1))) |
舉例:無限數列
毋過,讀者會問,到底這有 sím 物路用?貧惰計算 ê 一个好處,tiō 是 thang 表示一个「
f(x) = 2x, x = 0,1,2,…
ê 級數,beh 按怎表示 nih?咱人通觀察伊 ê recursion(
咱通觀察,這个數列通表示做 (inf-series 20),其中
(inf-series n) := (cons n (inf-series 2×n))。
所以咱 kám 有可能 kā tse 用程式表示出來?巧 ê 讀者應該 ê 知影,因為無限級數內底有無限 ê 數,電腦無可能一改算出來,而且 iā 無可能儲存 hiah-ni̍h tse ê 數,所以準若有人好膽執行這个程式,系統會
1 | (define (inf-series n) |
所以嚴格計算無法度表示。是講,咱人無愛 kā 無限級數 ê 所有項攏展示,只要算 kàu 咱愛 ê 項 tiō 可以。所以,tse ē-tàng 用貧惰計算來表示囉,ná án-ne:
; (delay ...) 是咱 buài tsit-má 算 ê 所在。 |
假使咱 beh 第二項 x2,tiō 愛共包佇 delay 內底 ê promise 強制執行,若:
; 第二項出來矣,毋過生出別个 promise。 |
咱人 tiō 通實做:
1 | ; 定義無限級數 |
試驗:
> (inf-series 1) |
實作
欲做這真簡單,delay tiō 是 kā 函數用無任何引數 ê lambda 包起來。force tiō 是 kā 予 lambda 包起來 ê 執行。毋過準若用 define 定義,因為會代先嚴格計算 beh khah 慢算 ê 表達式,致 kàu 無合咱所愛 ê,所以定著愛用 macro ê 方式來寫:
(define-syntax my-delay |
force tiō 是:
(define (my-force my-promise) |
> (define delayed-procedure (my-delay (+ 1 2))) |
參考
(Scheme) 17. Lazy evaluation of Yet Another Scheme Tutorial by Takafumi Shido
21. Delayed evaluation and infinite lists in Scheme of Functional Programming in Scheme : With Web Programming Examples by Kurt Nørmark, Department of Computer Science, Aalborg University, Denmark
註腳