Gleam Guards
Guards add extra conditions to pattern match branches. A pattern describes the shape of a value; a guard further tests whether the pattern's bound variables satisfy a boolean condition. Together, they make case expressions precise and expressive.
What Is a Guard?
A guard is the if clause that appears after a pattern in a case branch:
case value {
pattern if <boolean condition> -> result
_ -> fallback
}A branch with a guard matches only when both the pattern and the guard condition are true. If the pattern matches but the guard fails, Gleam moves to the next branch.
Guard Evaluation Flow
──────────────────────────────────────────────────
case score {
n if n >= 90 -> "A"
n if n >= 80 -> "B"
_ -> "Other"
}
score = 85
Branch 1: n = 85, 85 >= 90? No → skip
Branch 2: n = 85, 85 >= 80? Yes → match! → "B"
Guards with Numeric Ranges
pub fn classify_bmi(bmi: Float) -> String {
case bmi {
b if b <. 18.5 -> "Underweight"
b if b >=. 18.5 && b <. 25.0 -> "Normal"
b if b >=. 25.0 && b <. 30.0 -> "Overweight"
_ -> "Obese"
}
}
BMI Classification Chart
──────────────────────────────────────────────────
BMI Range │ Category
──────────────┼──────────────────
Below 18.5 │ Underweight
18.5 – 24.9 │ Normal
25.0 – 29.9 │ Overweight
30.0 and above│ Obese
Guards with String Conditions
import gleam/string
pub fn validate_username(name: String) -> String {
case name {
n if string.length(n) == 0 -> "Username cannot be empty"
n if string.length(n) < 3 -> "Too short — minimum 3 characters"
n if string.length(n) > 20 -> "Too long — maximum 20 characters"
_ -> "Username is valid"
}
}Guards with Multiple Conditions
Combine conditions in a guard using && and ||:
pub fn ticket_price(age: Int, is_student: Bool) -> Float {
case age {
a if a < 5 -> 0.0
a if a >= 5 && a <= 12 -> 50.0
a if a >= 13 && a <= 17 -> 100.0
_ if is_student -> 150.0
a if a >= 60 -> 150.0
_ -> 250.0
}
}
Ticket Pricing Matrix
──────────────────────────────────────────────────
Age Range │ Student? │ Price
─────────────┼──────────┼────────
Under 5 │ Any │ Free
5 – 12 │ Any │ ₹50
13 – 17 │ Any │ ₹100
Any │ Yes │ ₹150
60+ │ Any │ ₹150
Default │ No │ ₹250
Guards Cannot Produce Side Effects
Guards must be pure boolean expressions. They cannot call functions that print, write files, or perform network requests. Functions used in guards must return Bool and have no side effects.
Valid Guard Expressions
──────────────────────────────────────────────────
✓ n > 0
✓ n >= 10 && n <= 100
✓ string.length(s) > 3
✓ list.length(items) == 0
✓ is_valid(x) ← only if is_valid returns Bool
Invalid Guard Expressions
──────────────────────────────────────────────────
✗ io.println("checking") ← side effect
✗ let x = 5 ← binding not allowed
Guards with Captured Variables
When a pattern binds a variable, that variable is available in the guard:
let items = ["apple", "banana", "cherry"]
case items {
[first, ..rest] if string.starts_with(first, "a") ->
"Starts with A: " <> first
[first, ..rest] ->
"First item: " <> first
[] ->
"Empty list"
}
// "Starts with A: apple"Practical Example — Loan Eligibility
import gleam/io
pub fn loan_decision(age: Int, income: Float, credit_score: Int) -> String {
case #(age, credit_score) {
#(a, _) if a < 21 -> "Too young for a loan"
#(_, cs) if cs < 600 -> "Credit score too low"
#(a, cs) if a >= 21 && cs >= 750 && income >=. 50000.0 ->
"Approved — Premium rate"
#(a, cs) if a >= 21 && cs >= 650 && income >=. 30000.0 ->
"Approved — Standard rate"
_ -> "Not eligible"
}
}
pub fn main() {
io.println(loan_decision(25, 60000.0, 780)) // Approved - Premium rate
io.println(loan_decision(19, 45000.0, 700)) // Too young
io.println(loan_decision(30, 25000.0, 620)) // Not eligible
}Summary
Guards Quick Reference
──────────────────────────────────────────────────
Syntax: pattern if condition -> result
Rules:
• Condition must be a Bool expression
• Bound pattern variables are available in guard
• Multiple conditions: use && and ||
• No side effects in guards
• If guard fails, Gleam tries the next branch
Guards turn simple pattern matching into a full decision engine. Combined with expressive patterns, they let you encode business rules directly in the structure of your code — where the compiler keeps them honest.
