Ricardo
Ricardo

Reputation: 1798

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!

Upvotes: 5

Views: 362

Answers (2)

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66803

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.

Upvotes: 7

Matthias Benkard
Matthias Benkard

Reputation: 15769

lazy_from_val is a function rather than syntax. Thus,

# 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

Upvotes: 2

Related Questions