I’ll make a stab at breaking this up as I know how you feel! First, here’s the code formatted for easier reading (use three ```ocaml at start of the line and end with ``` on a newline).
(* Make Map of subtrees of t and their corresponding flow table locations *)
let flow_table_subtrees (layout : flow_layout) (t : t) : flow_subtrees =
let rec subtrees_for_table
(table : Field.t list)
(t : t)
(subtrees : t list) : t list
=
match FDD.unget t with
| Leaf _ -> subtrees
| Branch ((field, _), tru, fls) ->
if (List.mem table field) then
t :: subtrees
else
subtrees_for_table table tru subtrees
|> subtrees_for_table table fls
in
let meta_id = ref 0 in
List.map layout ~f:(fun table -> subtrees_for_table table t [])
|> List.filter ~f:(fun subtrees -> subtrees <> [])
|> List.foldi ~init:Map.Poly.empty ~f:(fun tbl_id accum subtrees ->
List.fold_right subtrees ~init:accum ~f:(fun t accum ->
Map.add accum ~key:t ~data:(tbl_id,(post meta_id))))
The first line (surrounded by (* *)) is a comment. The next line
let flow_table_subtrees (layout : flow_layout) (t : t) : flow_subtrees =
is the start of the function definition of flow_table_subtrees which has two parameters: layout and t. Unusually for OCaml the author has type annotated the parameters. So, (layout : flow_layout) means that there is a parameter layout that has type flow_layout and (t : t) means t has type t.
In addition, the return type of the function is defined (after the last :) as flow_subtrees. This level of type annotation is not common in OCaml as the compiler can almost always infer types.
Next the function subtrees_for_table is defined to be recursive (the rec keyword, by default OCaml functions are non-recursive).
let rec subtrees_for_table
(table : Field.t list)
(t : t)
(subtrees : t list) : t list
=
This function has 3 parameters: table, tand subtrees and all have been type annotated so table is a Field.t list and so on. The return type is defined as a t list. Note that as subtrees_for_table is defined inside the function it will only be visible within this function.
Now we get to the body of subtrees_for_table:
match FDD.unget t with
| Leaf _ -> subtrees
| Branch ((field, _), tru, fls) ->
This matches the return value from FDD.unget t (the module FDD is defined outside of this code) with two possible variants: Leaf and Branch (ignoring the bits after the variant name). The variant type being match here has a declaration something like:
type tree = Leaf of ? | Branch of ((Field.t * ?) * (t * t)
The '?'s are not part of the language and just mean I don’t know the type. Checkout variant types for more detail.
In the case of Leaf it has one parameter but we aren’t interested in the value so we use _ to ignore it (and stop the compiler compaining about unused values). When the return value of FDD.unget t matches Leaf _ the value of the match statement becomes the value of the parameters subtrees.
The case of Branch is a little more complex. The Branch match
| Branch ((field, _), tru, fls) ->
matches the variant Branch and the variables field, tru and fls have their values set to the correspondence values of the variant. The body of the Branch variant is then executed:
if (List.mem table field) then
t :: subtrees
else
subtrees_for_table table tru subtrees
|> subtrees_for_table table fls
What this says is: If field is a member of the table list then the value of the if is t pre-pended to subtrees and this will be the value of the match statement
The else case is a little more complex: The first step is to recursively execute subtrees_for_table table tru subtrees which itself returns a t list.
Before going on the ‘|>’ operator is worth looking at: let ( |> ) x f = f x. so let f a = a + 1 in 5 |> f will return 6. It gets more interesting with the partial application of functions. In the above subtrees_for_table table fls is partially applied and is in fact a function that takes 1 argument, a t list. Check out currying for more info.
So, now subtrees_for_table table tru subtrees |> subtrees_for_table table fls actually means (subtrees_for_table table fls) (subtrees_for_table table tru subtrees), which is a t list and is the value of the if…else and as a result the match statement.
In either case the value of the match becomes the value of the function subtrees_for_table.
For the rest, check out lists in real world ocaml as well as the ref cell section in the imperative programming chapter.