05_Pattern_Matching

when Expressions (Pattern Matching)

What are when Expressions?

This is kinda where the whole idea for Baba Yaga started. Pattern matching is an approach to flow control. We do this in Baba Yaga using the when expression. It provides pattern matching functionality, allowing you to match values against patterns and execute different code based on the match.

/* Pattern matching with when expressions */
result : when x is
  0 then "zero"
  1 then "one"
  _ then "other";

Baba Yaga's pattern matching syntax has a lot of insporations, but especially cond patterns, Gleam's pattern matching, and Roc's, too.

Basic Examples

/* Simple pattern matching */
x : 5;
result : when x is
  0 then "zero"
  1 then "one"
  2 then "two"
  _ then "other";
/* Result: "other" */

/* Pattern matching with numbers */
grade : 85;
letter_grade : when grade is
  90 then "A"
  80 then "B"
  70 then "C"
  60 then "D"
  _ then "F";
/* Result: "B" */

Pattern Types

Literal Patterns

/* Match exact values */
result : when value is
  true then "yes"
  false then "no"
  _ then "maybe";

Wildcard Pattern

/* _ matches anything */
result : when x is
  0 then "zero"
  _ then "not zero";

Function Reference Patterns

/* Match function references using @ operator */
double : x -> x * 2;
square : x -> x * x;

which : x -> when x is
  @double then "doubling function"
  @square then "squaring function"
  _ then "other function";

test1 : which double;
test2 : which square;

As is called out elsewhere, too, the @ operator is required when matching function references in patterns. This distinguishes between calling a function and matching against the function itself.

Boolean Patterns

/* Match boolean values */
result : when condition is
  true then "condition is true"
  false then "condition is false";

Complex Examples

/* Grade classification with ranges */
score : 85;
grade : when score is
  when score >= 90 then "A"
  when score >= 80 then "B"
  when score >= 70 then "C"
  when score >= 60 then "D"
  _ then "F";
/* Result: "B" */

/* Multiple conditions */
x : 5;
y : 10;
result : when x is
  when x = y then "equal"
  when x > y then "x is greater"
  when x < y then "x is less"
  _ then "impossible";
/* Result: "x is less" */

Advanced Pattern Matching

You can match multiple values with complex expressions:

/* FizzBuzz implementation using multi-value patterns */
fizzbuzz : n ->
  when (n % 3) (n % 5) is
    0 0 then "FizzBuzz"
    0 _ then "Fizz"
    _ 0 then "Buzz"
    _ _ then n;

/* Test the FizzBuzz function */
result1 : fizzbuzz 15;  /* "FizzBuzz" */
result2 : fizzbuzz 3;   /* "Fizz" */
result3 : fizzbuzz 5;   /* "Buzz" */
result4 : fizzbuzz 7;   /* 7 */

You can access table properties directly in patterns:

/* User role checking */
user : {role: "admin", level: 5};

access_level : when user.role is
  "admin" then "full access"
  "user" then "limited access"
  _ then "no access";
/* Result: "full access" */

You can use function calls in patterns. Be warned, though -- they require parentheses to help disambiguate them from other references, though.

/* Even/odd classification */
is_even : n -> n % 2 = 0;

classify : n ->
  when (is_even n) is
    true then "even number"
    false then "odd number";

/* Test the classification */
result1 : classify 4;  /* "even number" */
result2 : classify 7;  /* "odd number" */

Function calls in patterns must be wrapped in parentheses!

This'll work:

when (is_even n) is true then "even"
when (complex_func x y) is result then "matched"

This won't work:

when is_even n is true then "even"  /* Ambiguous parsing */

You can nest when expressions for complex logic:

/* Nested pattern matching */
x : 5;
y : 10;
result : when x is
  0 then when y is
    0 then "both zero"
    _ then "x is zero"
  1 then when y is
    1 then "both one"
    _ then "x is one"
  _ then when y is
    0 then "y is zero"
    1 then "y is one"
    _ then "neither special";
/* Result: "neither special" */

Using when with Functions

/* Function that uses pattern matching */
classify_number : x -> when x is
            0 then "zero"
  (x % 2 = 0) then "even"
  (x % 2 = 1) then "odd"
            _ then "unknown";

/* Use the function */
result1 : classify_number 0;   /* "zero" */
result2 : classify_number 4;   /* "even" */
result3 : classify_number 7;   /* "odd" */

Common Patterns

/* Value classification */
classify_age : age -> when age is
  (age < 13) then "child"
  (age < 20) then "teenager"
  (age < 65) then "adult"
  _ then "senior";

/* Error handling */
safe_divide : x y -> when y is
  0 then "error: division by zero"
  _ then x / y;

/* Status mapping */
status_code : 404;
status_message : x -> 
    when x is
      200 then "OK"
      404 then "Not Found"
      500 then "Internal Server Error"
        _ then "Unknown Error";

When to Use when pattern matching

Use when expressions when:

  • You need to match values against multiple patterns
  • You want to replace complex if/else chains
  • You're working with enumerated values
  • You need to handle different cases based on value types
  • You want to make conditional logic more readable
  • You need to match multiple values simultaneously (multi-value patterns)
  • You want to access table properties in patterns (table access)
  • You need to use function results in patterns (function calls with parentheses)
  • You're implementing complex validation logic (multi-field validation)
  • You need to match function references (using @ operator)

Don't use when expressions when:

  • You only have a simple true/false condition (use logical operators)
  • You're working with complex nested conditions (consider breaking into functions)