DriftScript
Documentation

Guide

Records

data declarations, literals that give every field a value, and why records have no methods.

A record is data with named fields, and it has no methods. That second half looks like a limitation and is the decision that makes hot reload work.

Every field, every time

A record literal gives every field a value. Leaving one out is an error rather than a silent fill from the declared default: a literal that looks complete while half of it came from somewhere else is the same ambiguity as an implicit null, one level up. Defaults belong to the generated constructor, which is a different operation with a different name.

// A record, a mutation, and the two things the compiler will not let you skip.
//
// `door` is `mut`, so its fields may be written. `by` is not, so it may only be read. A record
// literal gives every field a value: there is no partial construction.

import { clamp } from "std/math"

data Door {
    open: bool = false
    angle: f32 = 0
}

fn swing(door: mut Door, by: f32) {
    door.angle = math.clamp(door.angle + by, 0, 180deg)
    if door.angle > 45deg {
        door.open = true
    }
}

fn closed() -> Door {
    return Door { open: false, angle: 0 }
}

Behaviour is a function that takes the record

Because behaviour lives outside the record, the compiler can tell a read from a write, and a function can be replaced while live instances carry on working. A method would be a function whose identity is bound to the value it hangs off, and replacing one would mean finding every value.

A condition never parses as a record literal

`if door { }` is a condition and its block, never a literal. A condition that genuinely needs one parenthesises it.