Unions

A union is a tagged set of variants — a value that is exactly one of several alternatives. Each variant carries its own payload (or none), and pattern matching dispatches on the tag.

Variant body forms

Three shapes are accepted: a record body with named fields, a typeref body for a single positional payload, or a unit body with no payload.

union Shape {
  Circle { radius: f64, stroke: f64 }   // record variant
  Polygon i32                            // typeref variant
  Empty                                  // unit variant
}

Constructing variants

Use Union::Variant syntax — record payloads in braces, typeref payloads in parentheses, unit constructors bare.

a = Shape::Circle { radius: 5.0, stroke: 0.5 }
b = Shape::Polygon(7)
c = Shape::Empty

Inferring the variant from shape

When the expected type is a union — a union-typed field, an element of a list<Union>, or a function parameter — you can drop the Union::Variant tag and write a bare record. The variant is inferred from the record's field shape, so the explicit tag becomes optional.

// `series: list<ChartSeries>` — the variant is inferred per element.
series = [
  { name: "North", values: [42.0, 55.0] },   // inferred ChartSeries::Of
  { name: "South", values: [30.0, 48.0] },
]

The match is by field-name set (and field types when two variants share a name set), so it only works when the shape is unambiguous; a bare record matching no variant is a build error. Reach for the explicit Union::Variant { … } form to disambiguate or to be explicit. A bare record with no expected union type stays an anonymous record value.

extends

A union can extends another, inheriting its variants and adding more — useful when a host wants to extend an open vocabulary without modifying the base declaration.

union BaseShape {
  Empty
}

union Shape extends BaseShape {
  Circle { radius: f64 }
  Square { side: f64 }
}