Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of OCaml's Lazy.lazy_from_val?

The doc of Lazy.lazy_from_val states that this function is for special cases:

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).

Which cases are they talking about?

If I create a pair of suspended computation from a value like:

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

What is the difference between these two? Because Lazy.lazy_is_val l1 and Lazy.lazy_is_val l2 both return true saying that the value is already forced!

like image 651
Ricardo Avatar asked Mar 18 '12 17:03

Ricardo


1 Answers

The special purpose would be if you need a lazy value but you sometimes have an already computed (non-lazy) value. You can use lazy_from_val to turn an already computed value into a (forced) lazy version of your value.

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

In this (contrived) example, you might wish to call f with an ordinary integer value (14, in this example). You can do it, but you need to use Lazy.lazy_from_val to make it work.

The key difference is that lazy takes an expression of type 'a and creates a suspended computation (in essence, a closure) of type 'a lazy_t. Lazy.lazy_from_val takes a pre-computed value of type 'a and converts it to a (pre-forced) value of type 'a lazy_t. If the expression has side-effects, the difference between the two can be seen.

# 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
# 

You could implement lazy operations directly using explicit closures and references. As Matthias Benkard points out, OCaml's lazy mechanism uses special syntax to make it less cumbersome to work with. I.e., lazy is an OCaml keyword, not a function.

like image 69
Jeffrey Scofield Avatar answered Sep 28 '22 07:09

Jeffrey Scofield