ESC
Type to search...
S
Soli Docs

Pattern Matching

Powerful pattern matching with match expressions, destructuring, and guard clauses.

Basic Match

match

Match a value against patterns and execute corresponding code.

let x = 42;
let result = match x
    42 => "the answer",
    0 => "zero",
    _ => "something else",
end
print(result);  # "the answer"

Guard Clauses

Add conditions to patterns using if guards:

let n = 5;
let category = match n
    n if n < 0 => "negative",
    0 => "zero",
    n if n > 0 && n < 10 => "single digit positive",
    n if n >= 10 && n < 100 => "two digit positive",
    _ => "large number",
end
print(category);  # "single digit positive"

# Practical example: HTTP status handling
def handle_status(code: Int) -> String
    match code
        code if code >= 200 && code < 300 => "Success: " + str(code),
        code if code >= 300 && code < 400 => "Redirect: " + str(code),
        404 => "Not Found",
        500 => "Internal Server Error",
        code if code >= 500 => "Server Error: " + str(code),
        _ => "Client Error: " + str(code),
    end
end

print(handle_status(200));  # "Success: 200"
print(handle_status(404));  # "Not Found"

Array Patterns

let numbers = [1, 2, 3];

# Match array length
let description = match numbers
    [] => "empty array",
    [_] => "single element array",
    [_, _] => "two element array",
    [_, _, _] => "three element array",
    _ => "array with more than 3 elements",
end

# Destructuring arrays
let result = match numbers
    [first] => "First element is: " + str(first),
    [first, second] => "First: " + str(first) + ", Second: " + str(second),
    [first, second, third] => "Three elements",
    [first, ...rest] => "First: " + str(first) + ", Rest has " + str(len(rest)) + " elements",
end

# Rest pattern
let arr = [1, 2, 3, 4, 5];
match arr
    [first, second, ...rest]
        print("First two: " + str(first) + ", " + str(second));
        print("Remaining: " + str(rest));  # [3, 4, 5]
    end
end

Hash Patterns

let user = {"name": "Alice", "age": 30, "city": "Paris"};

# Match hash structure
match user
    {} => "empty object",
    {name: n} => "name is: " + n,
    {name: n, age: a} => n + " is " + str(a) + " years old",
    {name: n, age: a, city: c} => n + " is " + str(a) + " years old and lives in " + c,
    _ => "unknown structure",
end

# Nested hash matching
let data = {
    "user": {"name": "Alice", "email": "[email protected]"},
    "posts": [{"title": "Post 1"}, {"title": "Post 2"}]
};

match data
    {user: {name: n}, posts: posts}
        print(n + " wrote " + str(len(posts)) + " posts");
    end
    _ => "no match",
end

Type-Based Dispatch

def describe_value(val: Any) -> String
    match val
        s: String => "String with " + str(len(s)) + " characters",
        n: Int => "Integer: " + str(n),
        f: Float => "Float: " + str(f),
        b: Bool => "Boolean: " + str(b),
        arr: Array => "Array with " + str(len(arr)) + " elements",
        h: Hash => "Hash with " + str(len(h)) + " keys",
        null => "Null value",
        _ => "Unknown type: " + type(val),
    end
end

print(describe_value("hello"));     # "String with 5 characters"
print(describe_value(42));          # "Integer: 42"
print(describe_value([1, 2, 3]));   # "Array with 3 elements"

Wildcard Pattern

_ Wildcard / Default Case

Matches any value. Use as a default/catch-all case.

let status = "unknown";
let message = match status
    "active" => "User is active",
    "inactive" => "User is inactive",
    _ => "Status: " + status,  # Default case
end