Records: Projection and Update
Records are key/value structures with named fields. Rex supports:
- field projection:
base.field - record update:
{ base with { field = expr } }
At the value level, “record” literals are written like dicts:
{ x = 1, y = 2 }
At the type level, record types are written with ::
let p: { x: i32, y: i32 } = { x = 1, y = 2 } in
p
Projection
type Point = Point { x: i32, y: i32 }
let p: Point = Point { x = 1, y = 2 } in p.x
Projection is accepted when the field is definitely available on the type (see Specification).
Tip: If you get a “field not definitely available” type error, it usually means the typechecker can’t prove which ADT variant you have. A
matchoften fixes it.
Update
type Point = Point { x: i32, y: i32 }
let p: Point = Point { x = 1, y = 2 } in
{ p with { x = p.x + 10 } }
Updates can set multiple fields at once:
type Point = Point { x: i32, y: i32 }
let p: Point = Point { x = 1, y = 2 } in
{ p with { x = 100, y = 200 } }
Updating record-carrying ADT variants
This is a common pattern:
type Sum = A { x: i32 } | B { x: i32 }
let s: Sum = A { x = 1 } in
match s
when A {x} -> { s with { x = x + 1 } }
when B {x} -> { s with { x = x + 2 } }
The match arms refine which constructor s has, allowing the update to typecheck.