Syntax

Kind

Construction

Record Literals

Nested Records

From Tables

Record Comprehensions

Accessing Fields

Dot Indexing

Nested Records

Assigning Fields

Records and Tables

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 y}.

{x:1, y:true}

The kind of a field can be specified with a type annotation:

{x<u8>:1, y<bool>:true}

Custom record kinds can be defined:

<point3>:=<{x<f64>,y<f64>,z<f64>}>p<point3>:={x:1.0, y:2.0, z:3.0}

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.

r:={x:3, y:false}

Field kinds can be specified explicitly:

r:={x<u8>:3, y:false}--

x is explicitly typed as u8, y is inferred as bool

Nested Records

Records can be nested:

r:={pos:{x:1, y:2}, label:"A"}--

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.

T:=
x<f64>
y<bool>
1.2 true
1.3 false
r:=T[1]--

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.

my-set:={1, 2, 3}{{x:i, y:i*i} | i <- my-set}

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

r:={x:1.2, y:true}r.x

Likewise, y can be accessed to return a bool value:

r.y

Nested Records

By chaining dot indexing, nested fields can be accessed:

r:={pos:{x:1, y:2}, label:"A"}r.pos.x

Assigning Fields

Records are immutable unless defined with the ~ operator.

~r:={x:1, y:2} r.x = 42 r

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.

~T:=
x<f64>
y<bool>
1.2 true
1.3 false
~r:=T[1]--

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.

T:=
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:

T[1]

Selecting multiple rows produces a table, not a set of records:

T[1..=2]--

returns a table