Chapter 7: Records, guards and deriving

Records

  • type T { … }
  • generic records
  • record update

A type with a single constructor named like the type can list its fields in braces: pub type Point { x: Float, y: Float } is exactly pub type Point { Point(x: Float, y: Float) }. The Gleam tab shows the long form it becomes.

Everything else works as with the long form: construction (Point(0.0, 0.0), or with labels), patterns like Player(name:, level: | _), and updates like Player(player | position: …).

A generic record declares its parameters as usual, Page(item), so the meaning of Page(Int) never depends on the order of the fields. A type that wraps a value without a label, like UserId(Int), is written in full.

Open in playground
//// A type with one constructor, named like the type, can list its fields
//// in braces: a record.

pub type Point { x: Float, y: Float }

pub type Player {
  name: String,
  level: Int,
  position: Point,
}

/// Generic records name their parameters, like any other type.
pub type Page(item) {
  items: List(item),
  number: Int,
  total: Int,
}

/// A value without a label is written in full.
pub type UserId {
  UserId(Int)
}

pub def describe(Player(name:, level: | _)) -> String {
  "#{name}, level #{int.to_string(level)}"
}

pub def move(player: Player, dx: Float) -> Player {
  Player(player | position: Point(player.position | x: player.position.x +. dx))
}

pub def main() {
  ada = Player(name: "Ada", level: 3, position: Point(0.0, 0.0))
  echo describe(ada)
  echo move(ada, 2.5).position
  echo Page(items: [UserId(1), UserId(2)], number: 1, total: 2)
}

This lesson's code is a module of a small Bea project, compiled and run by bea for this page: content/features/src/records.bea