How do I use a :=? assign-if-unset guard in a switch expression?
← Control Flow · Ref: Q1359
The switch (or 'given') expression accepts a guard in its header. The guard runs once, before matching; if it leaves the guard variable unset the whole switch body is skipped and the expression yields the returning variable's initial value.
SWITCH EXPRESSION WITH A :=? GUARD
Assign-if-unset (:=?) sets the control variable only when it is currently unset, then the switch matches on it:
tier as String? discount <- switch tier :=? lookupTier() with tier <- rtn as Integer: 0 case "gold" rtn: 20 case "silver" rtn: 10 default rtn: 5
If lookupTier() is unset, 'tier' stays unset, the body is skipped, and 'discount' is the initial 0.
SWITCH STATEMENT WITH A :=? GUARD
The same guard works without a returning variable:
level as String? switch level :=? lookupTier() with level case "gold" stdout.println("premium") default stdout.println("standard")
HEADER SHAPE
'switch <guard> with <control>' — the guard is the pre-flow; the value being matched comes after 'with'. Contrast ?= (guarded assignment, always assigns then checks) with :=? (assigns only when unset).
See Q75 for switch guards. See Q837 for the ?= guard in a switch expression. See Q68 for the switch expression. See Q1361 for guards across all expression-form constructs.
Example
defines module qa.controlflow.guardswitchexpression defines function lookupTier() <- rtn as String: "gold" defines program GuardSwitchExpressionDemo() stdout <- Stdout() // switch EXPRESSION with a :=? assign-if-unset guard tier as String? discount <- switch tier :=? lookupTier() with tier <- rtn as Integer: 0 case "gold" rtn: 20 case "silver" rtn: 10 default rtn: 5 stdout.println(`discount is ${discount}`) // switch STATEMENT with a :=? guard level as String? switch level :=? lookupTier() with level case "silver" stdout.println("standard tier") default stdout.println("premium tier")
Common mistakes
E02001 — The guard is the pre-flow and comes first; the matched control follows 'with'. Order is 'switch <guard> with <control>'. See ek9 -h E02001.
Incorrect:
discount <- switch tier with tier :=? lookupTier() <- rtn as Integer: 0 case "gold" rtn: 20 default rtn: 5
Correct:
discount <- switch tier :=? lookupTier() with tier <- rtn as Integer: 0 case "gold" rtn: 20 default rtn: 5
Other ways to ask this
- switch expression with a guarded assignment
- Can a switch that returns a value lazily initialise its control variable?
- assign-if-unset guard in a given/switch
- How do I default the switch control with :=? before matching?
Coming from another language?
Java: switch is a statement (or, since 14, an expression) but has no header guard and no isSet/assign-if-unset concept; you would default the variable in a separate statement. EK9: the switch/given expression takes a guard (<-, ?=, :=?) that can lazily initialise the control and skip the whole switch when unset, while still yielding the returning variable.
Keywords: default, unset, isset, expression, assign, guard, given, :=?, returning, case, control, switch