C+
Language · View as Markdown
v0.0.27 is a macOS / AppKit release. That is the supported path. Other platforms are not recommended; wait for a later version.

Pattern matching

match is exhaustive: missing a variant is a compile error (E0340). That is what makes it safe to add a variant later, since the compiler points you at every place that must handle it.

fn describe(s: Shape) -> i32 {
    return match s {
        Shape::Circle(r)         => (r as i32) *% 2,
        Shape::Rectangle(w, h)   => (w as i32) *% (h as i32),
        Shape::Square(side)      => (side as i32),
    };
}

Add a catch-all _ arm when you genuinely do not care about the rest:

return match c {
    Color::Red => 1,
    _          => 0,
};

if let: extract on the happy path

if let Maybe[i32]::Some(v) = m {
    #println(v);
}

guard let: match or diverge

guard let binds the value and forces the failure case to leave the scope, so the rest of the function reads straight through:

fn process(m: Maybe[i32]) -> i32 {
    guard let Maybe[i32]::Some(v) = m else { return 0 -% 1; };
    return v +% 1;          // `v` is in scope after the guard
}

The else block must diverge via return, break, continue, or loop. The compiler enforces that.

while let

while let Maybe[i32]::Some(v) = next() {
    #println(v);
}

var bindings: mutate the extracted value

if let, while let, and guard let also take var in place of let. The bound value(s) become mutable: guard var in the enclosing scope, if var / while var inside the body (fresh per iteration for while var).

fn bump(m: Maybe[i32]) -> i32 {
    guard var Maybe[i32]::Some(v) = m else { return 0 -% 1; };
    v = v +% 1;
    return v;
}

The let spellings and all pattern-let diagnostics (E0347 / E0348 / E0349 / E0350 / E0351) are unchanged. A guard var complement binding (else |Pat|) stays immutable: it is scoped to the diverging else block.

These binding forms, together with the control-flow primitives, are how C+ does error handling without exceptions or a ? operator.