-
-
Notifications
You must be signed in to change notification settings - Fork 0
Records Sums And Tuples
Product types collect values that exist together. Sum types describe alternatives. Pudu gives both forms names, and pattern matching recovers their components without casts or tag tests.
type Point = { x: Int, y: Int }
fn translate(point: Point, dx: Int, dy: Int) -> Point {
Point{x: point.x + dx, y: point.y + dy}
}
A record declaration is nominal: two declarations with the same fields are distinct types. Field names are part of construction and access, so their order does not carry meaning at a use site. The checker verifies that construction supplies the declared fields with their declared types.
type Shape = Circle(Int) | Rectangle(Int, Int) | Empty
fn area(shape: Shape) -> Int {
match shape {
case Circle(radius) => 3 * radius * radius
case Rectangle(width, height) => width * height
case Empty => 0
}
}
Each constructor belongs to the declared sum. A variant may carry no payload, positional fields,
or a record-shaped payload. The declaration fixes the corresponding construction and pattern
form. A match over a closed sum must cover every variant unless a catch-all arm covers the
remainder.
Record-shaped variants keep field names at both boundaries:
type Event = Connected{ host: Str, port: Int } | Closed{ reason: Str }
fn describe(event: Event) -> Str {
match event {
case Connected{host, port: _} => "connected to " + host
case Closed{reason} => reason
}
}
The shorthand field pattern host binds a name with the same spelling. port: _ names the field
and discards its value.
Tuples are fixed-size heterogeneous products written by position.
fn swap[A, B](pair: (A, B)) -> (B, A) {
match pair {
case (left, right) => (right, left)
}
}
A tuple pattern can be used by match or directly in a for loop head. Ordinary let binds one
name and does not destructure a tuple. Tuples are useful at narrow boundaries—returning two related
values or representing a map entry. A record is preferable when the positions need enduring names.
type UserId = Int
type Handler = fn(Str) -> Result[Str, Str]
type Pair[A, B] = (A, B)
Aliases are transparent: UserId and Int denote the same type to the checker. They can document
an interface but do not create a distinct domain type. A record or single-variant sum creates a
nominal boundary when accidental interchange must be rejected.
Sum and record declarations may refer to named types according to the checker’s recursive type rules. The interpreter represents the resulting values structurally; native layout and deterministic destruction are not yet part of the implementation contract.
- Modules And Imports
- Values, Bindings, And Blocks
- Types And Inference
- Records, Sums, And Tuples
- Functions Generics And Traits
- Pattern Language
- Control Flow And Patterns
- Iteration And Loops
- Failure And Propagation
- Numbers And Collections
- Sets Maps And Sequences
- Keyed Structures
- Trees And Hierarchies
- Standard Library
- Output Formatting And Testing
- Tasks And Scopes
- Compile-Time Evaluation
- Typed Macros
- References And Unsafe
- Worked Programs