Can I use a '<-' guard's variable in the else block of the same if?
← Control Flow · Ref: Q2002
Not to read it before you assign it. Every later 'else if' and 'else' of an 'if name <- lookup()' chain runs BECAUSE the guard failed - name was unset - so reading name there finds nothing: that read is E08270, and testing it with 'name?' is always false (E08089).
A WRITE stays legal, and a read after the write is fine. Re-point it in a later head and check it: 'else if name := lookup("fallback") then name?'.
The rule covers a guard that is the whole condition. With a 'then' condition, or over a Boolean (unset OR false), the later block may see a value, so it is not checked.
See Q74 for the guard in an if and Q2001 for guards over a Boolean.
Example
defines module qa.controlflow.guardvariableinelse defines function lookup() -> key as String <- rtn as String: key defines program GuardVariableInElse() stdout <- Stdout() if found <- lookup(String()) stdout.println(`found ${found}`) else stdout.println("nothing found") if name <- lookup(String()) stdout.println(`name ${name}`) else if name := lookup("fallback") then name? stdout.println(`using ${name}`) else stdout.println("no name at all")
Common mistakes
E08270 — The else runs because 'found' was unset, so reading it there finds nothing. Use it inside the guarded block, or assign it first. See ek9 -h E08270 for details.
Incorrect:
stdout.println(`nothing found for ${found}`)
Correct:
stdout.println("nothing found")
E08089 — In a later block of the chain the guard's variable is always unset, so checking it is always false. Re-point it first: 'else if name := lookup(...) then name?'. See ek9 -h E08089 for details.
Incorrect:
else if name?
Correct:
else if name := lookup("fallback") then name?
Other ways to ask this
- What does E08270 mean?
- Why is reading the guard variable in the else an error?
- How do I give a guard variable a value in a later else if?
- Why is 'else if name?' always false after 'if name <- lookup()'?
Coming from another language?
Swift: 'if let name = lookup() { } else { }' - name is not even in scope in the else. Kotlin: 'lookup()?.let { } ?: run { }' - same. EK9 keeps the variable in scope for the whole chain so a later head can assign it, and rejects the reads that can only find nothing.
Keywords: declaration guard, else if, guard, scope, E08089, else, unset, E08270