rixed@happyleptic.org wrote:
> > Oops.
> > The following makes it possible for f to be garbage-collected:
>
> ...?
> Because the fact that the fun calls f does not count as a reference ?
The anonymous function in the second version of Martin's function doesn't
"call" [f] (at least directly): imagine if the `None case had been written
with [g]s instead:
let lz f =
let result = ref (`None f) in
fun () ->
match !result with
`None g ->
(try
let y = g () in
result := `Result y;
y
with e ->
result := `Exn e;
raise e
)
| `Result y -> y
| `Exn e -> raise e
The [fun] only "calls" (uses) [result]. In the first version, [f] could only
be collected after the [fun] had been collected (i.e. when the lazy value
itself is collected - not good). In the second version, [f] can be garbage
collected if the lazy value has already been forced (meaning that "[result =
`Result y | `Exn e]" so there will be no more references to [f]) - a clear
optimisation with no performance penalty in terms of space.
The optimisation would be irrelevant if the ocaml compiler was lazy and just
included all of the scope in the closure for [fun], but minimising (and
eliminating, where possible) closures is a critical part of ML compilers
(I'd be amazed if it's not covered in all of the books you've mentioned
previously and I wish I could remember the name usually given to the
problem... but I'm sure someone will chip in with it!)
David