Structs
A struct is a top-level list of typed fields, one per line. Calling the struct name with one argument per field, in order, creates a new value:
struct Point do
int x
int y
end
Point p = Point(1, 2)
p.x += 10
print(p.x, p.y) // 11 2A field can have a default value, written after =, and values can be given
by field name, in any order, after those given by position. Fields with a
default can be left out:
struct Server do
str host = "localhost"
int port = 8080
bool secure = false
end
Server local = Server()
Server api = Server("example.com", secure: true, port: 443)A default is evaluated each time a struct is made, so each one gets its own array or map; it may use constants and call functions, but not variables. The values given are evaluated in the order written, then the defaults.
Struct values are references. Assignment and function calls share the same record rather than copying it, so a function can update a field of its argument. Fields can have any type, including the struct itself, which makes recursive data such as lists and trees possible:
struct Node do
int value
Node next
end
Node list = Node(1, Node(2, null))
print(list.next.value) // 2Field access composes with calls and indexes, as in nodes[0].next.value.
str, bytes, arrays, maps, and structs are reference types: they accept null and
can be compared with it. Two structs compare by identity with == and !=. Reading
or writing a field through null terminates the program with a runtime error.
Structs cannot be printed or used in arithmetic.
Enums and structs may be used before their declaration. Their names cannot be reused for variables, functions, or other types.
Generic structs
A struct can take type parameters in brackets after its name, which its fields use like types:
struct Pair[A, B] do
A first
B second
end
struct Stack[T] do
T[] items = []
end
Pair[str, int] entry = Pair("apples", 3)
Stack[f64] readings = Stack()
push(readings.items, 2.5)
Pair[int, int] origin = Pair[int, int](0, 0)Pair[str, int] and Pair[int, str] are different types, and the type
arguments must always be written in a type. When a struct is made, its type
arguments are those written after its name, as in Pair[int, int](0, 0), or else
those the place it goes expects, such as the declared type of a variable,
or else they come from the values given, in order; when none of these tells,
as for Stack() on its own, the compiler asks for them. Fields read and
written through a Pair[str, int] have the types str and int, and the
defaults of a generic struct are checked for each set of types it is made
with.
A generic struct can be used anywhere a type can: in arrays and maps, in the
fields of other structs, in the values that enum members carry, and with the
type parameters of generic functions and enums, as in
func top[T](Stack[T] s) T. Its fields can hold the struct itself, as in
Node[T] next. The compiler generates a C struct for each set of type
arguments the program uses.