Skip to main content
Interpolation

Strings stay lightweight

Use string interpolation directly instead of building formatting helpers first.

fun main() {
    let name = "Ada";
    let score = 98;
    println("${name}: ${score}");
}
References

Shared state is explicit

When two closures need the same mutable state, aliasing is visible in the source.

fun main() {
    var n = 0;
    let r: &var i64 = &var n;
    let inc = () -> () { r += 1; };
    inc();
}
ADTs

Enums drive control flow

Pattern matching stays central: model the alternatives, then make each case explicit.

fun describe(v: Perhaps<i64>) -> String {
    match v {
        Perhaps::Some { value: n } => "${n}",
        Perhaps::None => "empty",
    }
}
Generics

Write it once, for any T

A generic function like first<T> works over any item type, with no boilerplate specialization.

fun first<T>(items: T[]) -> Perhaps<T> {
    if (items.len() == 0) {
        return Perhaps::None;
    }
    return Perhaps::Some { value: items[0u64] };
}
Aspects

Capabilities without inheritance

An aspect declares a capability, extend attaches it to a type, and generic bounds can rely on it directly.

aspect Printable {
    fun print(self);
}


extend Point: Printable {
    fun print(self) {
        println("(${self.x}, ${self.y})");
    }
}
Error handling

? propagates, .yolo() unwraps

Result and Perhaps share both: ? bubbles an Err up automatically, and .yolo() unwraps when you are sure.

fun double_parse(s: String) -> Result<i64, ParseError> {
    let n = parse_positive(s)?;   // returns Err immediately on failure
    return Result::Ok { value: n * 2 };
}


fun main() {
    println(double_parse("42").yolo());   // 84
}