Which ways of combining the guard operators does the compiler reject, and what should I write instead?
← Control Flow · Ref: Q1982
Each pre-flow operator says one thing, and three combinations say something you did not mean. The compiler rejects them.
1. :=? ON A VARIABLE THAT IS ALWAYS SET (E08095)
setting <- 7 setting :=? fetchReading() // can never assign
':=?' fills an UNSET variable. When the compiler can prove the variable is set, the ':=?' can never apply (and its right side is never even evaluated). Start from a value that may be unset ('setting <- fetchNothing()'), or assign with ':='.
2. A ':=' HEAD WITH NO CONDITION (E07340)
if latest := fetchReading()
':=' in a head assigns and checks nothing, so an 'if' with only ':=' has no condition at all. To enter only when the new value is set, say so: 'if latest := fetchReading() then latest?'. An assignment never yields a value, so outside a head the check is its own step: 'latest := fetchReading()' then 'found := latest?'.
3. RE-POINTING A CHECKED OPTIONAL (E08040)
Inside 'if current?', writing 'if current := fetchName() then current?' (or a plain 'current := fetchName()') re-points current. 'if current?' made current.get() safe in that block - for THAT value. The assignment may put an empty Optional there. Take a NEW variable ('if replacement <- fetchName()').
The program shows each correct form. See Q1980 for the pre-flow operators, Q1981 for assigning and then checking, Q79 for :=?, Q86 for Optional safety.
Example
defines module qa.controlflow.guardfamily.misuses defines function fetchReading() <- rtn as Integer: 42 fetchNothing() <- rtn as Integer: Integer() fetchName() <- rtn as Optional of String: Optional("Steve") defines program GuardMisusesFixed() stdout <- Stdout() //:=? only means something when the variable may be unset setting <- fetchNothing() setting :=? fetchReading() stdout.println(`setting=${setting}`) //An assignment never yields a value - assign, then check the new value latest <- fetchNothing() found <- Boolean() latest := fetchReading() found := latest? stdout.println(`found=${found} latest=${latest}`) //A ':=' head checks nothing - the explicit 'then latest?' is the gate if latest := fetchReading() then latest? stdout.println(`guarded: latest=${latest}`) //Inside the block a check made safe, take a NEW variable rather than re-point the checked one current <- fetchName() if current? if replacement <- fetchName() stdout.println(`replacement: ${replacement.get()}`) stdout.println(`current: ${current.get()}`)
Common mistakes
E08095 — 'setting' starts with a literal, so it is always set and the ':=?' below it can never assign. ':=?' is for a variable that may be unset. See ek9 -h E08095 for details.
Incorrect:
setting <- 7
Correct:
setting <- fetchNothing()
E07340 — ':=' in a head is a plain assignment that checks nothing, so an 'if' with only ':=' has no condition. Add 'then latest?' to enter only when the new value is set. See ek9 -h E07340 for details.
Incorrect:
if latest := fetchReading()
Correct:
if latest := fetchReading() then latest?
E08040 — 'if current?' made current.get() safe for the value it checked; the inner head's ':=' always assigns, so it could put an empty Optional in its place and the later current.get() would fail. Take a new variable instead. See ek9 -h E08040 for details.
Incorrect:
if current := fetchName() then current? stdout.println(`replacement: ${current.get()}`)
Correct:
if replacement <- fetchName() stdout.println(`replacement: ${replacement.get()}`)
Other ways to ask this
- Which pre-flow mistakes does the EK9 compiler reject?
- Why is a ':=' head with no condition a compile error?
- Can I re-point an Optional inside 'if opt?'?
- Why does ':=?' on a variable I just initialised say it can never apply?
- What are the common mistakes with :=, :=? and <- in a control-flow head?
Coming from another language?
Kotlin: 'x = x ?: y' and 'if (y?.also { x = it } != null)' are legal and easy to get wrong; EK9 gives each intent its own operator and rejects the combinations that hide an assignment that never applies or a head that checks nothing. Java: re-assigning a variable after an isPresent() check compiles and fails at runtime with NoSuchElementException - in EK9 that is a compile error.
Keywords: compile error, E08095, Optional, <-, never applies, :=, always set, E07340, E08040, misuse, :=?, guard