I'm mystified by the and
keyword in OCaml. Looking through this code, I see
type env = {
(* fields for a local environment described here *)
}
and genv {
(* fields for a global environment here *)
}
then later,
let rec debug stack env (r, ty) = (* a function definition *)
and debugl stack env x = (* another function definition *)
What's going on here? Does the and
keyword just copy the last type
, let
, or let rec
statement? Is there such thing as an and rec
statement? Why would I want to use and
instead of just typing let
or type
, making my code less brittle to refactoring? Is there anything else I should know about?
The and
keyword is used either to avoid multiple let
(first example, I never use it for this but why not) or for mutually recursive definitions of types, functions, modules...
As you can see in your second example :
let rec debug stack env (r, ty) =
...
| Tunresolved tyl -> o "intersect("; debugl stack env tyl; o ")"
...
and debugl stack env x =
...
| [x] -> debug stack env x
...
debug
calls debugl
and vice versa. So the and
is allowing that.
[EDIT] It bothered me not to give a proper example so here is one example that you'll often see :
let rec is_even x =
if x = 0 then true else is_odd (x - 1)
and is_odd x =
if x = 0 then false else is_even (x - 1)
(* second version *)
let rec is_even x =
x = 0 || is_odd (x - 1)
and is_odd x =
x <> 0 && is_even (x - 1)
(You can find this example here)
For mutually recursive types, it's harder to find a configuration but following this wikipedia page we would define trees
and forests
as follow
type 'a tree = Empty | Node of 'a * 'a forest
and 'a forest = Nil | Cons of 'a tree * 'a forest
As an example, a forest composed of the empty tree, the singleton tree labeled a
and a two nodes tree with labels b
and c
would then be represented as :
let f1 = Cons (Empty, (* Empty tree *)
Cons (Node ('a', (* Singleton tree *)
Nil), (* End of the second tree *)
Cons (Node ('b', (* Tree composed by 'b'... *)
Cons (Node ('c', (* and 'c' *)
Nil),
Nil)
),
Nil (* End of the third tree *)
)
)
);;
And the size function (counting the number of nodes in the forest) would be :
let rec size_tree = function
| Empty -> 0
| Node (_, f) -> 1 + size_forest f
and size_forest = function
| Nil -> 0
| Cons (t, f) -> size_tree t + size_forest f
And we get
# size_forest f1;;
- : int = 3