record
A record is a collection of named fields, where each field has a name and a kind. Records group heterogeneous values into a single structured value, similar to a row in a table or a struct in other languages.
Syntax
Records are written using curly braces {} with named fields. Each field is written as name: value and fields are separated by commas.
{ x: 1, y: true }
{ name: "Alice", age: 42, active: true }
When parsed and rendered, this code will appear as:
{x:1, y:true}{name:"Alice", age:42, active:true}
Records may be written inline or across multiple lines for readability:
{
x: 1.2,
y: true,
label: "pt1"
}
Kind
In general, a record has the kind:
<{field1<kind1>,field2<kind2>}>The kind of a record is determined by the names and kinds of its fields. The kind of a filed is inferred from its value, but can also be specified explicitly. For example, the following record has two fields, x of kind f64 and y of kind bool. Therefore the kind is {x.
The kind of a field can be specified with a type annotation:
Custom record kinds can be defined:
Construction
There are three ways to create a record:
Record literals
Selecting a row from a table
Comprehensions
Record Literals
Record literals are written using curly braces {} with named fields. Each field is written as name: value and fields are separated by commas.
Field kinds can be specified explicitly:
x is explicitly typed as u8, y is inferred as bool
Nested Records
Records can be nested:
record with nested record field
Nested records can also be written across multiple lines for readability:
r := {
pos: {
x: 1
y: 2
}
label: "A"
}
From Tables
Selecting a single row from a table produces a record whose fields correspond to the table columns.
x<f64> | y<bool> |
|---|---|
| 1.2 | true |
| 1.3 | false |
r is a record {x<f64>,y<bool>}
Record Comprehensions
Set comprehensions can be used to create sets of records. Each element in the resulting set is a record constructed from the comprehension's output expression.
Likewise, list comprehensions can create lists of records:
my-list := [1 2 3]
[{x: i, y: i * i } | i <- my-list]
Accessing Fields
Fields are accessed using dot indexing ..
Dot Indexing
Likewise, y can be accessed to return a bool value:
Nested Records
By chaining dot indexing, nested fields can be accessed:
Assigning Fields
Records are immutable unless defined with the ~ operator.
If you try to assign to a field of an immutable record, an error is raised:
r:={x:1, y:2} r.x = 42 --Error: cannot assign to field of immutable record
When records originate from tables, updates are performed at the table level, not on the record value itself.
x<f64> | y<bool> |
|---|---|
| 1.2 | true |
| 1.3 | false |
r is a mutable record
r.x = 42 --Update field x in record r
T.x[1]--Access updated value from table T
In this example, updating r.x also updates the corresponding value in table T.
Records and Tables
Tables are conceptually sets of records. Each row in a table corresponds to one record with the same field names as the table columns.
x<u8> | y<bool> |
|---|---|
| 1 | true |
| 2 | false |
| 3 | true |
Here the type of T is a table with two columns, x of kind u8 and y of kind bool. A single row of the table can be selected to produce a record of a corresponding kind:
Selecting multiple rows produces a table, not a set of records:
returns a table