Reputation: 25812
I am just curious about these two functions in Lazy
.
From the doc:
val from_fun : (unit -> 'a) -> 'a t
from_fun f is the same as lazy (f()) but slightly more efficient.
I then had a look at the source
let from_fun (f : unit -> 'arg) =
let x = Obj.new_block Obj.lazy_tag 1 in
Obj.set_field x 0 (Obj.repr f);
(Obj.obj x : 'arg t)
I guess Obj
is used to directly allocate memories for from_fun
. But why exactly does it boost the efficiency? or what is the difference between Lazy.from_fun
and lazy (f())
?
val from_val : 'a -> 'a t
from_val v returns an already-forced suspension of v.
This is for special purposes only and should not be confused with lazy (v).
I really do not understand these. To me, Lazy.from_val 5
and lazy(5)
both returns int lazy.t
which has a concrete value of 5. Why is Lazy.from_val
is for special purposes? and what kind of special purposes?
Upvotes: 1
Views: 94
Reputation: 9030
It's just my guess: let's compare the following:
let z1 = lazy (print_newline ())
let z2 = Lazy.from_fun print_newline
using ocamlc -dlambda
:
(setglobal Lz!
(let
(z1/1008 =
(makemutable 246
(function param/1012 (apply (field 31 (global Pervasives!)) 0a)))
z2/1009 =
(apply (field 2 (global Lazy!)) (field 31 (global Pervasives!))))
(makeblock 0 z1/1008 z2/1009)))
z1
is a lazy value created from a function of the code function param/1012 -> Pervasives.print_newline ()
, while z2
is created directly from Pervasives.print_newline
. z1
can be slightly inefficient because of the extra lambda abstraction.
Just as the documentation says, Lazy.from_val
simply creates a lazy value from an already computed value without any suspension. You can check it by trying Lazy.from_val (print_string "hello")
and lazy (print_string "hello")
. The former immediately prints hello
, but the latter does not.
Upvotes: 2