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}