模組 Stdlib.Lazy

module Lazy: Lazy

type 'a t = 'a CamlinternalLazy.t 

類型為 'Lazy.t 的值是一種延遲計算,稱為暫停 (suspension),其結果類型為 'a。特殊的表達式語法 lazy (expr) 會建立 expr 計算的暫停,但不會立即計算 expr 本身。 「強制執行 (Forcing)」暫停將會計算 expr 並傳回其結果。使用特殊模式語法 lazy(pattern) 比對暫停也會計算底層表達式,並嘗試將其綁定到 pattern

      let lazy_option_map f x =
      match x with
      | lazy (Some x) -> Some (Lazy.force f x)
      | _ -> None
    

注意:如果 lazy 模式出現在模式匹配的多個 case 中,即使在模式匹配最終選擇的 case 之外,lazy 表達式也可能被強制執行。在上面的範例中,暫停 x 總是會被計算。

注意:lazy_t 是編譯器用於 lazy 關鍵字的內建類型建構子。您不應直接使用它。請始終使用 Lazy.t 來代替。

注意:Lazy.force 不是並行安全的。如果您在多個纖程 (fiber)、系統執行緒 (systhread) 或網域 (domain) 中使用此模組,則需要新增一些鎖定。但是,該模組可確保記憶體安全,因此,並行存取此模組不會導致當機,但行為是未指定的。

注意:如果程式使用 -rectypes 選項進行編譯,則類型檢查器會接受以下形式的病態遞迴定義 let rec x = lazy xlet rec x = lazy(lazy(...(lazy x))),並且在強制執行時,會導致格式錯誤的值,從而在垃圾回收器和其他執行時間系統的部分中觸發無限迴圈。如果沒有 -rectypes 選項,則類型檢查器會拒絕此類病態遞迴定義。

exception Undefined

當從多個纖程、系統執行緒或網域並行強制執行暫停,或當暫停嘗試遞迴地強制執行自身時,會引發此例外。

val force : 'a t -> 'a

force x 強制執行暫停 x 並傳回其結果。如果 x 已被強制執行,Lazy.force x 會再次傳回相同的值,而無需重新計算。如果它引發了例外,則會再次引發相同的例外。

迭代器

val map : ('a -> 'b) -> 'a t -> 'b t

map f x 傳回一個暫停,當強制執行時,會強制執行 x 並將 f 應用於其值。

它等同於 lazy (f (Lazy.force x))

關於已強制求值的暫停的推理

val is_val : 'a t -> bool

is_val x 如果 x 已被強制執行且未引發例外,則傳回 true

val from_val : 'a -> 'a t

from_val v 先評估 v(如同任何函式一樣),並傳回其結果的已強制執行的暫停。它與 let x = v in lazy x 相同,但在某些情況下使用動態測試來最佳化暫停的建立。

val map_val : ('a -> 'b) -> 'a t -> 'b t

map_val f x 如果 x 已被強制執行,則直接應用 f,否則其行為與 map f x 相同。

x 已被強制執行時,此行為會節省暫停的建構,但另一方面,它會執行更多可能無用的 eager 工作,如果您從不強制執行函式結果的話。

如果 f 引發例外,當 is_val x 時將立即引發該例外,否則只會在強制執行 thunk 時引發。

如果 map_val f x 未引發例外,則 is_val (map_val f x) 等於 is_val x

進階

以下定義僅適用於進階用途;它們需要熟悉 lazy 編譯方案才能適當使用。

val from_fun : (unit -> 'a) -> 'a t

from_fun flazy (f ()) 相同,但效率略高。

只有在已定義函式 f 時才應使用它。特別是,寫 from_fun (fun () -> expr) 總是比 lazy expr 效率低。

val force_val : 'a t -> 'a

force_val x 強制執行暫停 x 並傳回其結果。如果 x 已被強制執行,force_val x 會再次傳回相同的值,而無需重新計算。

如果 x 的計算引發例外,則無法指定 force_val x 引發相同的例外還是 Lazy.Undefined