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

时间:2012-03-18 17:39:55

标签: 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).

他们在谈论哪些案例?

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

let l1 = lazy 123
let l2 = Lazy.lazy_from_val 123

这两者有什么区别?因为Lazy.lazy_is_val l1Lazy.lazy_is_val l2都返回 true ,表示该值已被强制执行!

2 个答案:

答案 0 :(得分: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

在这个(人为的)示例中,您可能希望使用普通整数值(在此示例中为14)调用f。您可以这样做,但您需要使用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
# 

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

答案 1 :(得分:2)

lazy_from_val是函数而不是语法。因此,

# let id = fun x -> x;;
val id : 'a -> 'a = <fun>
# Lazy.lazy_is_val (lazy (id 123));;
- : bool = false
# Lazy.lazy_is_val (Lazy.lazy_from_val (id 123));;
- : bool = true