Does ':=?' evaluate its right-hand side when the target is already set?
← Control Flow · Ref: Q1961
No. The right-hand side of ':=?' runs ONLY when its target is unset (or not yet initialised). When the target is already set, ':=?' neither assigns nor evaluates the right side - so a call there is not made at all. That makes ':=?' the assignment form of the coalescing '?:': 'found :=? value' is 'found := found ?: value'.
THE TWO OPERATORS
count := value ALWAYS assign value to count (an unset value included) found :=? value assign value to found ONLY if found is unset; otherwise value is not even evaluated
RECORD WHETHER AN ASSIGNMENT GAVE A VALUE, BUT ONLY THE FIRST TIME
Assign, then fall back with ':=?' on the set-check:
count := fetchCount() // count is always assigned found :=? count? // found takes the result only if it had none
An assignment never yields a value in EK9, so the set-check is its own step.
A ':=?' ON A TARGET THE COMPILER KNOWS IS SET IS AN ERROR
If flow analysis proves the target is already set ('found <- false' then 'found :=? count?'), the ':=?' can never apply, and the compiler rejects it (E08095).
See Q1960 for re-pointing inside a safe access block (E08040), Q79 for ':=?' and Q759 for assigning and then checking.
Example
defines module qa.flow.guard.assignifunset defines function fetchCount() <- rtn as Integer: 42 alreadyFound() <- rtn as Boolean: false defines program GuardThenAssignIfUnsetDemo() stdout <- Stdout() count <- Integer() found <- Boolean() stdout.println(`before: count set=${count?} found set=${found?}`) count := fetchCount() found :=? count? stdout.println(`after: count=${count} count set=${count?} found=${found}`) found :=? alreadyFound() stdout.println(`second: found=${found}`) stdout.println("Done")
Common mistakes
E08095 — Declared with a value, found is provably set, so the following 'found :=? count?' can never apply. Declare it unset ('Boolean()') when ':=?' is meant to fill it. See ek9 -h E08095 for details.
Incorrect:
found <- false
Correct:
found <- Boolean()
Other ways to ask this
- Is the right of ':=?' evaluated lazily?
- How do I record whether an assignment gave a value, but only the first time?
- How do I combine assign-if-unset with a set-check?
- When does ':=?' call the function on its right?
- What does error E08095 mean for ':=?'?
Coming from another language?
C#: 'found ??= Compute()' only evaluates Compute() when found is null, the same laziness as EK9's ':=?'. Kotlin: 'found = found ?: compute()'. JavaScript: 'found ??= compute()'. EK9: 'found :=? compute()' - and because an assignment never yields a value, a set-check of another assignment is written as its own step: 'count := fetchCount()' then 'found :=? count?'.
Keywords: assign if unset, set check, E08095, lazy, conditional evaluation, boolean, :=?