Does ':=?' initialise a variable declared with no value, even when the value it assigns is unset?
← Data Flow Safety · Ref: Q2003
Yes - where the ':=?' always runs. A variable declared with no value ('x as Integer?') counts as unset, so 'x :=? f()' assigns whatever f() returned. That is an object - present, maybe unset, never absent - so x is initialised and every later use is legal: arithmetic on an unset Integer gives an unset result, not a crash.
It counts only where it always runs: a statement, the FIRST 'if' pre-flow, a 'while', 'for', 'switch' or 'try' pre-flow, a 'do' body, a 'finally'. An 'else if' pre-flow, an if/case/loop body, a try body and a catch may not run, so a variable filled only there is E08020 at its later use. 'if third :=? fetch(true)' in the head initialises third; the same ':=?' inside the if body does not.
On a variable the compiler can prove is already set, ':=?' can never apply (E08095).
See Q79 for ':=?' and Q29 for unset variables.
Example
defines module qa.dataflow.assignifunsetinitialises defines function fetch() -> wanted as Boolean <- rtn as Integer: Integer() if wanted rtn: 42 defines program AssignIfUnsetInitialises() stdout <- Stdout() first as Integer? first :=? fetch(true) stdout.println(`first set=${first?} value=${first}`) second as Integer? second :=? fetch(false) stdout.println(`second set=${second?}`) total <- second + 1 stdout.println(`second + 1 set=${total?}`) third as Integer? if third :=? fetch(true) stdout.println(`third filled by the if head: ${third}`) stdout.println(`third after the if set=${third?}`)
Common mistakes
E08020 — Inside the if body ':=?' may not run, so 'third' might still have no value when it is read afterwards. Put ':=?' where it always runs - the if head or a statement. See ek9 -h E08020 for details.
Incorrect:
if fetch(true)? third :=? fetch(true)
Correct:
if third :=? fetch(true) stdout.println(`third filled by the if head: ${third}`)
Other ways to ask this
- Can I use a variable after 'x as Integer?' and 'x :=? f()'?
- What happens when ':=?' assigns an unset value?
- Why is my ':=?' inside an if not enough to initialise the variable?
- Is a variable filled by ':=?' ever absent?
Coming from another language?
Kotlin: 'var x: Int? = null; x = x ?: f()' leaves x null when f() returns null. C#: 'x ??= F()' the same. EK9 has no null: ':=?' always stores an object, which may be unset, so the variable is initialised either way.
Keywords: E08020, uninitialised, assign-if-unset, initialise, absent, unset, :=?, definite assignment