How do I use a guard expression as a standalone assignment that returns Boolean?
← Control Flow · Ref: Q759
The guard expression operator (?=) can be used as a standalone assignment expression that returns a Boolean. The expression evaluates the right-hand side (RHS), checks if it is SET, and if so assigns it to the target variable. The Boolean result indicates whether the assignment occurred.
STANDALONE GUARD EXPRESSION
Unlike using ?= in control flow guards (if, while), this pattern captures the Boolean result:
name as String? guardResult <- name ?= getValue()
Here guardResult is a Boolean: true if getValue() returned a set value (and name was assigned), false otherwise.
WHEN THE RHS IS SET
If getValue() returns a set String, the assignment happens and the result is true:
name as String? result <- name ?= getValue() // result is true, name is now the returned value
WHEN THE RHS IS UNSET
If the RHS returns an unset value, no assignment occurs and the result is false:
existing <- "already here" result <- existing ?= getEmpty() // result is false, existing is unchanged
KEY DIFFERENCE FROM :=? AND ?= IN GUARDS
The three related patterns:
name :=? checks TARGET isSet, assigns if unset if name ?= checks SOURCE isSet, controls flow result <- name ?= checks SOURCE isSet, returns Boolean
The standalone form returns Boolean rather than controlling a block.
See Q74 for guard variables in if. See Q77 for guard variables in while. See Q79 for guarded assignment :=? operator.
Example
defines module qa.flow.guard.expression.boolean defines function getValue() <- rtn <- String() rtn: "hello" getEmpty() <- rtn <- String() defines program GuardExpressionBooleanDemo() stdout <- Stdout() // === GUARD EXPRESSION WITH SET RHS === name as String? guardResult <- name ?= getValue() stdout.println(guardResult) stdout.println(name) // === GUARD EXPRESSION WITH UNSET RHS === existing <- "already here" guardResult2 <- existing ?= getEmpty() stdout.println(guardResult2) stdout.println(existing) stdout.println("Done")
Common mistakes
E50030 — The guard expression ?= returns a Boolean, not the type of the assigned value. Declaring the result as String triggers E50030 because Boolean and String are incompatible. Use type inference with '<-' to get the correct Boolean type. See ek9 -h E50030 for details.
Incorrect:
guardResult as String: name ?= getValue()
Correct:
guardResult <- name ?= getValue()
Other ways to ask this
- Can I use ?= outside of an if or while statement?
- How does the guard expression ?= return a Boolean result?
- What does guardResult <- name ?= getValue() do in EK9?
Coming from another language?
Java: No direct equivalent. Must write: 'Optional<String> opt = getValue(); boolean assigned = opt.isPresent(); if (assigned) name = opt.get();'. Three separate statements. Kotlin: 'val result = getValue()?.also { name = it } != null'. Requires nullable types and scope functions. Python: 'result = getValue(); assigned = result is not None; name = result if assigned else name'. Manual and error-prone. EK9: 'result <- name ?= getValue()' is a single expression combining assignment and Boolean result.
Keywords: assignment, conditional, return, operator, null-safe, boolean, expression, standalone, guard, safe, source, result, check, isset