Match Expressions

Match Expressions

Match expressions provide pattern matching for clean, exhaustive branching.

Basic Syntax

match value {
    pattern1 => result1,
    pattern2 => result2,
    _ => default_result
}

The _ is a wildcard that matches any value not handled by previous arms.

Matching Integers

function describe(x: i32) i32 {
    return match x {
        1 => 100,
        2 => 200,
        3 => 300,
        _ => 0
    };
}
 
function main() i32 {
    return describe(2);  // Returns 200
}

Match as Expression

Match is an expression, so it returns a value that can be used directly:

function main() i32 {
    var x = 2;
    var result = match x {
        1 => 10,
        2 => 20,
        _ => 0
    };
    return result;  // 20
}

You can use match anywhere an expression is expected:

function main() i32 {
    var x = 1;
    var y = 10 + match x {
        1 => 5,
        _ => 0
    };
    return y;  // 15
}

Block Bodies

Use braces for multi-statement arm bodies:

function main() i32 {
    var x = 2;
    match x {
        1 => {
            var a = 10;
            return a + 5;
        },
        2 => {
            var b = 20;
            return b + 5;
        },
        _ => {
            return 0;
        }
    };
    return 0;
}

Matching Booleans

function main() i32 {
    var flag = true;
    return match flag {
        true => 1,
        false => 0,
        _ => 99
    };
}

Matching Enums

Match works naturally with enum types:

enum Color { Red, Green, Blue }
 
function to_code(c: Color) i32 {
    return match c {
        Color.Red => 1,
        Color.Green => 2,
        Color.Blue => 3,
        _ => 0
    };
}
 
function main() i32 {
    var c: Color = Color.Green;
    return to_code(c);  // 2
}

Match as Statement

Use match as a statement for side effects:

function main() i32 {
    var x = 2;
    var result = 0;
    match x {
        1 => { result = 10; },
        2 => { result = 20; },
        _ => { result = 99; }
    };
    return result;  // 20
}

Return from Match Arms

You can return from the enclosing function inside a match arm:

function process(x: i32) i32 {
    match x {
        1 => { return 10; },
        2 => { return 20; },
        _ => { return 99; }
    };
    return 0;  // Never reached if all cases return
}

Nested Match

Match expressions can be nested:

function main() i32 {
    var x = 1;
    var y = 2;
    return match x {
        1 => match y {
            1 => 11,
            2 => 12,
            _ => 10
        },
        2 => 20,
        _ => 0
    };  // Returns 12
}

No Match Fallthrough

If no arm matches and there's no wildcard _, execution continues after the match:

function main() i32 {
    var x = 99;
    match x {
        1 => { return 10; },
        2 => { return 20; }
    };
    return 0;  // Reached when x is neither 1 nor 2
}
⚠️

Without a wildcard arm, unmatched values will fall through silently. Consider always including a _ arm for safety.

Trailing Commas

Trailing commas are allowed:

match x {
    1 => 10,
    2 => 20,
    _ => 0,
}

Different Integer Sizes

Match handles different integer sizes (i32, i64, etc.):

function main() i32 {
    var x: i64 = 2;
    var result: i64 = match x {
        1 => 100,
        2 => 200,
        _ => 0
    };
    return result;  // 200
}

Destructuring Enum Payloads

Matching a payload-carrying enum destructures the payload into fresh bindings; _ skips a position:

enum Shape { Circle(f64), Rect(f64, f64), Empty }
 
function describe(s: ref Shape) f64 {
    return match s {
        Shape.Circle(r) => r,
        Shape.Rect(w, _) => w,
        Shape.Empty => 0.0
    };
}

Enum matches are exhaustive: cover every variant or add a _ arm. Duplicate arms and arms after _ produce unreachable-arm warnings.

For non-enum discriminants match remains equality-based. Guards, range patterns, and nested destructuring are planned for future versions.