### Records

• Records are like tuples, a data combiner, but with label names added for readability
• Record types must be declared just like OCaml variants.
• Again the fields are immutable by default (but there is a way to make them mutable ..)

Example: a simple record type to represent rational numbers

``````type ratio = {num: int; denom: int};;
let q = {num = 53; denom = 6};;
``````

Pattern matching

``````let rattoint r =
match r with
{num = n; denom = d} -> n / d;;
``````

Only one pattern matched so can again inline pattern in functions and lets

``````let rattoint {num = n; denom = d}  =  n / d;;
``````

Short-cut: pun between variable and field name (understand the above form before punning!!):

``````let rat_to_int {num; denom}  =  num / denom ;;
``````

Another short-cut if you only care about a few fields (very useful for a big record):

``````let get_num {num; _}  =  num;;
``````
• This is a special form of pattern, “`; _`” at the end of a record means don’t-care on all the missing fields.

Can also use dot projections a la C etc, but happy path is usually patterns

``````let rattoint r  =  r.num / r.denom;;
``````
• Dot notation to make an addition of ratios:
``````let add_ratio r1 r2 = {num = r1.num * r2.denom + r2.num * r1.denom;
denom = r1.denom * r2.denom};;
add_ratio {num = 1; denom = 3} {num = 2; denom = 5};;
``````

Pattern equivalent (can’t pun here because there are two records of same type):

``````let add_ratio {num = n1; denom = d1} {num = n2; denom = d2} =
{num = n1 * d2 + n2 * d1; denom = d1 * d2};;
add_ratio {num = 1; denom = 3} {num = 2; denom = 5};;
``````

Annoying shadowing issue when using dot: there is one global namespace of record labels

``````type newratio = {num: int; coeff: float};; (* shadows ratio's label num *)

fun x -> x.num;; (* x is inferred a newratio, the most recent num field defined *)
``````

Solution is to generally avoid dot; or declare `x`’s type if needed.

``````fun (x : ratio) -> x.num;; (* x is declared a ratio, avoiding previous shadowing *)
``````
• You can often leave out unused fields in a pattern:
``````let numerator {num}  = num;;
``````
• More punning.. if you can also use variables with the right names as a pun
``````let make_ratio num denom = {num;denom};;
make_ratio 1 2;;
``````
• Here is another shorthand for changing just some of the fields: `{r with ...}`
• Very useful for records with many fields, not so much here though
• Note “change” is not mutation again, it constructs a new record.
``````let clear_bad r =
match r with
| {denom = 0 } ->  {r with num = 0}
| _ -> r;;
clear_bad {num = 4; denom = 0};;
``````
• One more nice feature: labeling components of variants with records
``````type gbu = | Good of { sugar : string; units : int} | Bad of { spice: string; units : int} | Ugly
``````
• Observe that these inner record types don’t need to be separately declared
• Note that the “internal records” here are just that, internal – you can only use a `{sugar;units}` records inside a `Good` variant.

``````type 'a binnier_tree = Leaf | Node of {data :'a ; left : 'a binnier_tree; right : 'a binnier_tree}