Docs/Types

Structs

Small values that are copied instead of shared.

On this page

A struct is a small value type. Assigning it, passing it to a function, or returning it copies its fields.

Define a struct#

Valk
struct Point {
    x: int
    y: int (0)
}

fn main() {
    let origin = Point { x: 0 }
    let cursor = origin
    cursor.x = 10
    println(origin.x) // 0
    println(cursor.x) // 10
}

Fields, defaults and .{ ... } initializers work as in classes. A field that holds a class still refers to the same object after a copy.

Methods#

Valk
struct Size {
    width: int
    height: int

    fn area() int {
        return this.width * this.height
    }

    fn grow(by: int) {
        this.width += by
        this.height += by
    }

    static fn square(side: int) SELF {
        return SELF { width: side, height: side }
    }
}

fn main() {
    let size = Size.square(3)
    size.grow(1)
    println(size.area()) // 16
}

A method changes the value it is called on; this is a borrow of it.

Structs in an array#

list[i] hands out a copy of a struct element. To change the element, store it back with set or borrow it with &:

Valk
struct Score {
    points: int
}

fn main() {
    let scores = Array[Score]{ .{ points: 1 }, .{ points: 2 } }

    let first = scores[0]
    first.points = 10
    scores.set(0, first) !!

    let second = &scores[1]
    second.points = 20

    println(scores[0].points + scores[1].points) // 30
}

Compare and use as a key#

Structs compare field by field with == and work as HashMap keys without extra code:

Valk
struct Cell {
    row: int
    col: int
}

fn main() {
    let walls = HashMap[Cell, bool]{}
    walls.set(Cell { row: 1, col: 2 }, true)
    println(walls.has(Cell { row: 1, col: 2 })) // true
    println(Cell { row: 0, col: 0 } == Cell { row: 0, col: 1 }) // false
}

A struct with a float field, or one with its own $eq, needs a hash method as well.

A default value#

A static function marked $default gives the value used for T.$default_value:

Valk
struct Range {
    start: int
    count: int

    static fn empty() SELF $default {
        return SELF { start: 0, count: 0 }
    }
}

fn main() {
    let range: Range = Range.$default_value
    println(range.count) // 0
}

Struct or class#

struct class
Assignment copies the fields shares the object
Can be null only as ?T only as ?T
Implements interfaces no yes
Good for points, sizes, keys, small records objects with identity and shared state

Manual heap allocation of a struct with mem.new is covered in Unsafe code.