# `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. ```plaintext /* 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 ```plaintext /* 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 ```plaintext /* Match exact values */ result : when value is true then "yes" false then "no" _ then "maybe"; ``` ### Wildcard Pattern ```plaintext /* _ matches anything */ result : when x is 0 then "zero" _ then "not zero"; ``` ### Function Reference Patterns ```plaintext /* 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 ```plaintext /* Match boolean values */ result : when condition is true then "condition is true" false then "condition is false"; ``` ## Complex Examples ```plaintext /* 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: ```plaintext /* 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: ```plaintext /* 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. ```plaintext /* 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: ```plaintext when (is_even n) is true then "even" when (complex_func x y) is result then "matched" ``` This won't work: ```plaintext when is_even n is true then "even" /* Ambiguous parsing */ ``` You can nest `when` expressions for complex logic: ```plaintext /* 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 ```plaintext /* 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 ```plaintext /* 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)