If I have a String variable that might be unset, how can I conditionally assign a default value to it only when it has not been set yet?
← Operators and Expressions · Ref: Q1263
EK9 has a dedicated operator for 'assign if unset': :=? (guarded assignment). It assigns the right-hand value to the variable ONLY if the variable is currently unset. If the variable already has a value, the assignment is silently skipped — the existing value is preserved.
THE OPERATOR
variable :=? defaultValue
WORKED EXAMPLE
greeting as String: String() // unset greeting :=? "Hello, World" // assigned, because greeting was unset stdout.println(greeting) // "Hello, World"
greeting :=? "Goodbye" // SKIPPED, because greeting is now set stdout.println(greeting) // still "Hello, World"
AFTER THE FIRST GUARDED ASSIGNMENT, THE VARIABLE IS SET AND ALL FUTURE :=? CALLS ARE NO-OPS. This is exactly what 'assign default if unset' should mean.
WHY NOT IF + ASSIGNMENT?
The long-form equivalent works but is more verbose:
if not greeting? greeting: "Hello, World"
The :=? operator collapses this into one line. It is also IMPOSSIBLE to forget the negation — there is only one direction the operator can go.
NOT TO BE CONFUSED WITH OTHER OPERATORS
- := is plain assignment (always assigns, overwrites)
- :=? is guarded assignment (assigns only if unset)
- <- is declaration + first assignment (creates a new variable)
- <? is coalescing minimum (RETURNS the smaller value, completely different family)
See Q1264 for Integer guarded assignment. See Q1265 for Date. See Q1266 for custom record. See Q1226 for the contrast between :=? and <?.
Example
defines module qa.operators.guardedassignstring defines function //Sourced rather than a literal, so 'title' is genuinely already-set at runtime without //the compiler being able to prove it and reject the ':=?' below as dead (E08095). loadStoredTitle() <- rtn as String: "Untitled" defines program GuardedAssignStringDemo() stdout <- Stdout() greeting as String: String() greeting :=? "Hello, World" stdout.println(`first :=? : ${greeting}`) greeting :=? "Goodbye" stdout.println(`second :=? : ${greeting}`) // Variable that already has a value at declaration title <- loadStoredTitle() title :=? "Default Title" stdout.println(`pre-set :=? : ${title}`)
Common mistakes
E50001 — :=? is guarded ASSIGNMENT (assign if unset). <? is coalescing MINIMUM (returns the smaller value). They are completely different operators and serve different purposes. See ek9 -h E50001 for details.
Incorrect:
greeting <? "Hello, World"
Correct:
greeting :=? "Hello, World"
Other ways to ask this
- How do I assign a default to a String only when it is unset?
- Show me the EK9 way to provide a fallback value for an unset String.
- What is the operator that assigns only when the target is unset?
- Give me a worked example of conditional default assignment on a String.
Coming from another language?
Java: if (variable == null) variable = default. Kotlin: variable = variable ?: default. Python: variable = variable or default (works but conflates falsy with None). Rust: variable = variable.unwrap_or(default). JavaScript: variable = variable ?? default (nullish coalescing assignment). EK9: variable :=? default — direct, single operator, only assigns when target is unset.
Keywords: unset, fallback, guarded assignment, :=?, String, default value, conditional assignment