OCaml的Lazy.lazy_from_val的目的是什么?

Ric*_*rdo 5 ocaml lazy-evaluation

Lazy.lazy_from_val函数适用于特殊情况的状态文档:

val lazy_from_val : 'a -> 'a t
  lazy_from_val v returns an already-forced suspension of v This is for special purposes only and should not be confused with lazy (v).
Run Code Online (Sandbox Code Playgroud)

他们在谈论哪些案例?

如果我从以下值创建一对暂停计算:

let l1 = lazy 123
let l2 = Lazy.lazy_from_val 123
Run Code Online (Sandbox Code Playgroud)

这两者有什么区别?因为Lazy.lazy_is_val l1并且Lazy.lazy_is_val l2两者都返回真实的说价值已经被迫!

Jef*_*eld 7

特殊目的是,如果您需要一个惰性值,但有时您已经计算了(非惰性)值.您可以使用lazy_from_val将已计算的值转换为值的(强制)惰性版本.

let f lazyint =
    Lazy.force lazyint + 42

let li = lazy 4;;

# f li;;
- : int = 46
# f 14;;
    ^^
Error: This expression has type int but an expression was expected of type
         int Lazy.t = int lazy_t
# f (Lazy.lazy_from_val 14);;
- : int = 56
Run Code Online (Sandbox Code Playgroud)

在这个(人为的)示例中,您可能希望f使用普通的整数值(在此示例中为14)进行调用.你可以做到,但你需要使用Lazy.lazy_from_val它来使它工作.

关键区别在于lazy采用类型的表达式'a并创建类型的暂停计算(实质上是闭包)'a lazy_t. Lazy.lazy_from_val获取类型的预先计算值'a并将其转换为类型的(预强制)值'a lazy_t.如果表达具有副作用,则可以看出两者之间的差异.

# let p () = print_string "here\n"; 3 ;;
val p : unit -> int = <fun>
# let l1 = lazy (p ());;
val l1 : int lazy_t = <lazy>
# let l2 = Lazy.lazy_from_val (p ());;
here
val l2 : int Lazy.t = lazy 3
# f l1;;
here
- : int = 45
# f l2;;
- : int = 45
# 
Run Code Online (Sandbox Code Playgroud)

您可以使用显式闭包和引用直接实现延迟操作.正如Matthias Benkard指出的那样,OCaml的惰性机制使用特殊语法来减少使用它的麻烦.即,lazy是OCaml关键字,而不是函数.

  • “OCaml 的惰性机制使用特殊的语法”……以及特殊的 GC 功能来消除对强制值的间接访问(已变得无用)。 (2认同)