record ~default [(name1, d1); ...; (namen, dn)] recognizes List [List (Atom name'1 :: l'1); ...; List (Atom name'k :: l'k)] where for every name'i, there exists j such that name'i = namej, and l'i is accepted by dj. In case of success, the output value is fjn ( ... (fj1 default) ...) where the fjk are the values produced by djk.
The record combinator is useful to define decoders for records, in which fields may be given in any order. For every field, each decoder in the list produces a function that updates the corresponding field of the record. Each field entry is processed in the order in which they appear. Each field is optional.
Example:
# type t = { fst: int; snd: bool };;
type t = { fst : int; snd : bool; }
# let d =
record ~default:{ fst = 0; snd = false }
[ "fst", (let+ i = int in fun t -> { t with fst = i })
; "snd", (let+ b = bool in fun t -> { t with snd = b })
];;
val d: t decoder = <abstr>
The decoder d will produce the following results:
# run d (List [List [Atom "fst"; Atom "42"]; List [Atom "snd"; Atom "true"]])
- : t option = Some {fst = 42; snd = true}
# run d (List [List [Atom "snd"; Atom "false"]; List [Atom "fst"; Atom "42"]]);;
- : t option = Some {fst = 42; snd = false}
# run d (List [List [Atom "snd"; Atom "true"]]);;
- : t option = Some {fst = 0; snd = true}
# run d (List [List [Atom "fst"; Atom "42"]]);;
- : t option = Some {fst = 42; snd = false}
# run d (List [List [Atom "fst"; Atom "42"]; List [Atom "fst"; Atom "43"]]);;
- : t option = Some {fst = 43; snd = false}