Side-effects and top-level expressions in OCaml

ocaml, side-effects

Solution

When you write `let tmp = ref foo`, the expression `foo` is evaluated once, to produce a value which is stored in the reference. Accessing the reference returns this value, without re-evaluating the original expression.

The way to provoke re-evaluation is to use a function instead: if you write a function `(fun () -> foo)`, this is a value: it is returned as is, passed to functions, stored in references. And each time you apply an argument to this value, the expression `foo` is evaluated.

Clément's solution is good. The idea of

let counter =
  let count = ref (-1) in
  fun () -> incr count; !count

Is that the reference is allocated once, but incremented each time the function `fun () -> incr count; !count` is called. Having the reference local to the function avoids some of the pitfall of global variables. You can think of it as a "static variable" of the function `counter`, only it is a natural result of OCaml scoping and evaluation rules and not an additional, function-specific concept.

You can even write an even more general `vargen` generator, that creates fresh, independent counters each time it's called:

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

Problem

I am in trouble with ocaml. I want to make a function that will increment my counter every time I call it and concat my vargen string with the counter number and return this new string. What I did without success is: ``` let (counter : int ref) = ref 0;; let (vargen : string) = "_t";; let tmp = incr counter;ref (vargen ^ string_of_int !counter);; Printf.printf "%s\n" !tmp;; Printf.printf "%s\n" !tmp;; Printf.printf "%s\n" !tmp;; Printf.printf "%s\n" !tmp;; ``` But my output are always: ``` _t1 _t1 _t1 _t1 ``` And what my output should be: ``` _t0 _t1 _t2 _t3 ``` Any ideas to solve my problem guyz? Thks all.

Original source