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.

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

Guard Clauses

Add conditions to patterns using if guards:

n = 5
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

numbers = [1, 2, 3]

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

# Destructuring arrays
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
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

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
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.

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