模組 Lazy

module Lazy: sig .. end

延遲計算。


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
    

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

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

注意:Lazy.force 並非並發安全 (concurrency-safe)。如果您在多個纖程 (fibers)、系統線程 (systhreads) 或域 (domains) 中使用此模組,則需要新增一些鎖定。然而,該模組可確保記憶體安全,因此並發存取此模組不會導致崩潰,但行為未指定。

注意:如果程式使用 -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 work),如果您永遠不強制執行函數結果。

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

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

進階

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

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