How do guard variables work in switch statements?
← Control Flow · Ref: Q75
Guard variables in switch combine variable creation with an isSet check before the switch body executes. If the guard is unset, the entire switch (including default) is skipped.
BASIC SWITCH GUARD
Use the declaration operator (<-) with 'then' or 'with' to link the guard to the switch control:
switch value <- getResult() then value case 1 stdout.println("One") case 2 stdout.println("Two") default stdout.println("Other")
If getResult() is unset, nothing executes. No exception.
SWITCH EXPRESSION WITH GUARD
Switch expressions return a value. The guard protects the entire expression:
label <- switch priority <- getPriority() then priority <- rtn as String: "Unknown" case 1 rtn: "Low" case 2 rtn: "Medium" case 3 rtn: "High" default rtn: "Other"
If the guard is unset, the expression evaluates to the default return value ("Unknown").
KEYWORD INTERCHANGEABILITY
'with' and 'then' are synonyms. Use whichever reads better:
switch value <- getResult() with value switch value <- getResult() then value
Both are identical in behavior.
GIVEN/WHEN ALTERNATIVE
EK9 allows 'given' as a synonym for 'switch':
given value <- getResult() then value when 1 stdout.println("One")
See Q72 for more on given/when.
See Q63 for basic switch without guards. See Q68 for switch as expression. See Q74 for guards in if statements. See Q76 for guards in for loops. See Q243 for coalescing operators (??, ?:, <?, >?) that provide another approach to handling unset values.
Example
defines module qa.flow.guard.switchstatement defines function getPriority() <- rtn <- Integer() rtn: 2 getUnsetPriority() <- rtn <- Integer() defines program GuardSwitchDemo() stdout <- Stdout() // === BASIC SWITCH GUARD === switch priority <- getPriority() then priority case 1 stdout.println("Low priority") case 2 stdout.println("Medium priority") case 3 stdout.println("High priority") default stdout.println("Unknown priority") // === SWITCH EXPRESSION WITH GUARD === label <- switch priority <- getPriority() then priority <- rtn as String: "Unknown" case 1 rtn: "Low" case 2 rtn: "Medium" case 3 rtn: "High" default rtn: "Other" stdout.println("Priority label: " + label) // === GUARD WITH UNSET VALUE (entire switch skipped) === switch priority <- getUnsetPriority() then priority case 1 stdout.println("This should not print") default stdout.println("Default should not print either") stdout.println("After guarded switch with unset value")
Common mistakes
E01072 — EK9 has no return or break statements. Guard variables in switch combine declaration and isSet checking. Each case is self-contained with no fallthrough. See ek9 -h E01072 for details.
Incorrect:
priority <- getPriority() if not priority? return switch priority case 1 stdout.println("Low priority") break
Correct:
switch priority <- getPriority() then priority case 1 stdout.println("Low priority") case 2 stdout.println("Medium priority")
E01072 — EK9 has no return statement. Switch expressions use a declared return variable. The value is returned implicitly through the variable. See ek9 -h E01072 for details.
Incorrect:
switch priority <- getPriority() then priority case 1 return "Low"
Correct:
label <- switch priority <- getPriority() then priority <- rtn as String: "Unknown" case 1 rtn: "Low"
Other ways to ask this
- Can I guard a switch with a variable declaration?
- How does switch with guard work in EK9?
- What happens if a switch guard is unset?
Coming from another language?
Java: Java 21+ pattern matching in switch cannot combine guard declarations. Must write: 'var v = getValue(); switch (v) { ... }' as two steps. Variable leaks into outer scope. Kotlin: 'when' blocks cannot combine guard declaration with control expression. Must nest: 'val v = expr; when (v) { ... }'. Swift: 'switch expr' cannot combine optional binding with switch control. Must nest: 'if let v = expr { switch v { ... } }'. Go: No guard declarations in switch. Must declare and check separately. EK9: 'switch value <- getResult() then value' combines declaration, isSet check, and switch control in one line. Guards scope the variable to the switch block.
Keywords: switch, control, isset, null-safe, branch, declaration, expression, scope, given, safe, case, guard, flow, unset, condition