Overview
The metadef statement declares a new named type, essentially assigning a type expression to a name.
metadef name:type_expression.
Parameterised Types (Type Functions)
A metadef can declare type parameters with the takes keyword, producing a parameterised type alias — in effect a type function. The parameters are named after takes (comma-separated) and may be used anywhere inside the body’s type expression:
metadef vector takes T: T[].
metadef pair takes A, B: [A, B].
A parameterised alias is applied by writing it followed by its type arguments (juxtaposition), anywhere a type expression is valid. Applying it substitutes the arguments for the parameters and reduces to the resulting type:
metadef vector_int: vector int. // in the body of another metadef
A IS vector int = [1, 2, 3]. // in a binding's type annotation
P IS pair int str = [42, "hello"].
The reduced type is identical to writing the desugared form by hand — for example vector int is the same type as int[], and pair int str is the same type as [int, str].
Parameterised aliases compose — one may appear inside another’s body:
metadef vector takes T: T[].
metadef matrix takes T: vector (vector T). // a 2-D array of T
M IS matrix int = [[1, 2, 3], [4, 5, 6]].
Type-level reduction runs at compile time and is bounded so that a non-terminating or pathological type function fails cleanly rather than hanging. Reduction is limited to a nesting depth of 64 and a total of 1,048,576 reduction steps; exceeding either limit is a compile-time error. Legitimate deeply-nested types well within these bounds compile normally.
A few constructs are rejected at compile time:
takesparameters cannot be combined with type destructuring in the samemetadef.- A
takesparameter name cannot be repeated.
Type Destructuring in metadef
The record and tuple type expressions support the destructuring syntax, allowing you to declare multiple types in one metadef statement.
metadef t_person: (
$name->t_name: (
$fname->t_first_name: str,
$lname->str
),
$address->t_addr: (
$number->str,
$street->str,
$code->int
)).
metadef t_person: (
$name->t_name: (
$fname->t_first_name: str,
$lname->str
),
$address->t_addr: (
$number->str,
$street->str,
$code->int
)).
The example declares these types in one statement:
t_first_nameas stringt_nameas a record with two string fields $fname and $lnamet_addras a record with three fields, representing the addresst_personas a record of two fields, each of which is also a record, as shown.
Type destructuring is especially convenient in the specification of messaging protocols and database tables. Each row in a table could be a record of records (with, possibly, several levels of records). Declaring all of the involved types in one statement saves a lot of typing.