When you write let tmp = ref foo
, the expression foo
is evaluated once to get the value that is stored in the link. Accessing the link returns this value without re-evaluating the original expression.
A way to re-evaluate is to use a function: if you write a function (fun () -> foo)
, this value: it is returned as is, passed to the function, stored in links. And every time you apply an argument to this value, the expression foo
evaluated.
ClΓ©ment's solution is good. Idea
let counter = let count = ref (-1) in fun () -> incr count; !count
Is this link assigned once, but incremented every time the fun () -> incr count; !count
function is called fun () -> incr count; !count
fun () -> incr count; !count
. The presence of a function reference eliminates some error in global variables. You can consider it as a "static variable" of the counter
function, only this is a natural result of the OCAML rules for defining the scope and evaluation, and not for an additional functional concept.
You can even write an even more general vargen
generator, which creates fresh independent counters each time:
let make_vargen prefix = let count = ref (-1) in fun () -> incr count; prefix ^ string_of_int !count let fresh_t = make_vargen "t" let () = print_endline (fresh_t ()) (* t0 *) let () = print_endline (fresh_t ()) (* t1 *) let fresh_u = make_vargen "u" let () = print_endline (fresh_u ()) (* u0 *) let () = print_endline (fresh_t ()) (* t2 *) let () = print_endline (fresh_u ()) (* u1 *)
source share