Hi,
I’m wondering how the following facts (related to definition of closures) should be interpreted and whether it is in relation with evaluation, environment handling or semantics of reference (things are not very clear for me, reformulations would be welcome).
-
In pure programming style, I may write
let id x = x
as well aslet id = fun x -> x
and obtain exactly the same function (in the sense that they are observationnally equivalent). That is, whether I put arguments on the left or on the right-hand side of the defining=
, nothing changes. -
In contrast with that, let us compare the two function
mem_list
andmem_list'
below:
let mem_list =
let cache = ref [] in
fun n -> cache := n :: !cache ; !cache;;
mem_list 3 ;; (* outputs [ 3 ] *)
mem_list 4 ;; (* outputs [ 4 ; 3 ] *)
Thus, mem_list
memoizes a list given by the user and its type is weakly polymorphic '_weak1 -> '_weak1 list
. Now, let us change the code and just put the parameter n
on the left-hand side:
let mem_list' n =
let cache = ref [ ] in
cache := n :: !cache ; !cache;;
mem_list' 3 ;; (* outputs [ 3 ] *)
mem_list' 4 ;; (*outputs [ 4 ] *)
Now, there is no memoization, and the type of mem_list'
is (fully) polymorphic 'a -> 'a list
.
My surprise (which perhaps a little bit naive) comes from the fact that, morally, the variable n
is “pure variable” and I would have thought that it’s place does not matter.
So, I’m trying to understand why things happen like this and how to abstract them up:
- I guess that it has something to do with how environments are defined in OCaml. Is there a place where I may find the specification of environments?
- But has it something to do with the operational semantics of the
let ... in
construction in OCaml? Again, a pointer would be welcome