Records

Declaring records

A record is like a struct or class in other languages: it combines several values in named fields.
In this example, the record dimensions combines two floats width and height.

main void() a dimensions = 4, 2 area = a.width * a.height info log "area is {area}" dimensions record(width float, height float)

Generated functions

Declaring the record generates a function new dimensions(width float, height float) used in a dimensions = 4, 2.
It also generates functions width float(a dimensions) and height float(a dimensions) for accessing the fields.

"Nominal" records

Adding the nominal modifier changes the generated constructor's name from new to the same name as the record.
This is useful when the purpose of a record is to affect overloading, especially with for or with expressions ("For" and "with" expressions).

main void() info log crow.speak info log 1.duck.speak crow record nominal duck record(n nat) nominal speak string(_ crow) "caw!" speak string(a duck) "{a.n} quack!"

Mutable records

Like for a local variable, mut goes after a field name (but before the type) to make that field mutable.

main void() a dimensions = 4, 2 a.width := 5 info log "{a width}" dimensions record(width mut float, height mut float) mut

When you define a mut field, it generates a setter function.
In this example, it generates set-width void(a record, width float) and set-height void(a record, height float).

Expanded record syntax

For long records, you can instead write each field on its own line.

main void() r r = 1 r 2 info log "{r.x} {r.y}" r record nominal x nat y nat

This form makes room to comment on individual fields.