Your source of confusion is that you've misunderstood the meaning of the let
construct. It does not modify an object: it's not an assignment statement (. The let
construct gives a name to a value. The syntax of the let
construct is
let
name =
value in
expression
This causes name to refer to value in expression. The value is computed once, before binding the name to it. The scope of name is expression, so you can't use it to refer to value outside expression (the value, on the other hand, lives on until garbage collected).
The top-level let
construct is similar to the one in expressions, but does not have the in
expression part. The scope of the name is the rest of the program (it's as though there was an in
part containing everything below, at least until you get to modules).
You're trying to modify the top-level m
, but that is not let
's job: you would need an assignment for that. Ocaml has an assignment operator, :=
, which assigns to an existing reference. A reference is an object that can be modified. This is not automatic in Ocaml: unlike languages such as C, Java and Lisp, Ocaml does not use a single language feature to give names to values and to create modifiable storage. The ref
function creates a modifiable object; you assign it with :=
and use the !
operator to get its value:
let r_m = ref StringMap.empty;; (*the type of r_m is 'a StringMap.t ref*)
let rec count ke = match ke with
| [] -> []
| hd::tl -> r_m := StringMap.add hd 1 !r_m; [hd] @ count tl;;
This is however not very good Ocaml style. Ocaml supports this imperative style, but you should avoid it because imperative programming is more error-prone than functional programming. The functional style is to create a new value whenever you want to modify an object. Note that maps created by the Map
module are designed to support this style: add
returns a new object which coexists with the old object (i.e. it's a persistent data structure). Switching to a functional style requires that you change the interface of the count
function; it's something that you'd want to do anyway, to be able to use the count
function on different maps by passing the map as an argument. I refer you to Sami's answer for example code in good Ocaml style.