Skip to main content
View

Records & Constructors

This page covers record types, constructors, spread operators, and named type embedding in TypR.

Record literals and constructors​

let p <- :{ x = 1, y = 2 };                 # anonymous record (requires type context)
let p <- Point:{ x = 1, y = 2 };             # explicit constructor → transpiles to Point(x=1, y=2)
let q <- Point:{ ...p, y = 9 };              # runtime spread: structural merge, override after
let r <- mod$Point:{ x = 1, y = 2 };          # constructor qualified by module path

let arr <- IntBox:[1, 2, 3];                  # ArrayConstructorCall

Equivalent record literal forms: record{...}, object{...}, list{...}, :{...} — the form is determined by the shape of the fields, not the keyword: named fields name = value produce a record (Lang::List), positional values produce a tuple (Lang::Tuple) even with list{1, 2, 3}.


Spread — two distinct mechanisms​

# --- setup ---
type Point <- list { x: int, y: int };
type Tag <- list { z: int };
let source <- Point:{ x = 1, y = 2 };
let a <- source;
let b <- Tag:{ z = 3 };
# -------------

Point:{ ..source };     # "static" spread (nominal) — one per call
Point:{ ...source };    # "runtime" spread (structural) — one per constructor, several in a record literal
:{ ...a, ...b, z = 1 }; # record literal: multiple runtime spreads allowed, merged in order then overridden
FormNameAllowed inBehavior
..sourceStatic spreadConstructor callNominal; one per call
...sourceRuntime spreadConstructor call or literalStructural; merged in order

Named type embedding​

# --- setup ---
type Position <- list { x: int, y: int };
# -------------

type Widget <- list { embed coords: Position, label: char };

embed is a "soft" keyword — it is only recognized before name: Type with a trailing space, so a field actually named embed remains parsable.


The {...} rule for generic types​

A { ... } block following a parameterized type name always makes it a record constructor:

Tibble[3]{ id: int, active: bool }   # record constructor
Tibble[3]                             # just a parameterized alias (no braces)

Two violations are caught explicitly:

This example does not compile It shows what TypR rejects, on purpose.
Df[8, int]{ name: char }        # SyntaxError::RecordConstructorIndex
Array[5, { a: int }]             # SyntaxError::RecordInRecursiveParams