E08020: might be used before being initialised
What went wrong
You declared a variable but are using it BEFORE assigning it a value.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 4 (How do I read input from the user?)
Mutating operators require initialized lhs
ALL mutating operators require the left-hand side to already have a value:
- :=: (copy) and :~: (merge) - copy/merge INTO existing value
- +=, -=, *=, /= etc. - modify existing value
- ++, -- - increment/decrement existing value
These operators CANNOT work on uninitialized variables because there's nothing to copy into, merge with, or modify.
Stream and loop operands are reads too
A stream pipeline reads every variable it names, so each must hold a value first:
- the sink: 'results' in 'cat items > results'
- a tee target: 'side' in 'cat items | tee in side > out'
- a 'with' operand: 'transform' in '| map with transform'
- a 'by' operand: 'ordering' in '| sort by ordering'
- a head/skip/tail count: 'count' in '| head with count'
- a for-range step: 'step' in 'for i in 1 ... 10 by step'
Declare the variable with its value ('results <- List() of String', 'step <- 2'), or assign it before the stream or loop.
A path that ends in a throw
A path that ends in an unconditional throw never continues, so it does not count against a later read. With 'label as String?', an 'if' arm that assigns 'label: "large"' and an 'else' arm that is just 'throw Exception("Not positive")' leave 'label' set wherever the code after the if/else runs - every arm of a nested if/else or switch that throws counts. A throw inside an 'if' with no 'else' covers nothing (the other path still falls through), and a catch or finally runs AFTER the throw, so reading the variable there is still E08020 unless it was set before the try.
How to fix it
- Initialize at declaration: value <- initialValue
- Or ensure initialization happens before use
- For copy semantics, use: local <- Type(source) instead of :=:
Common causes
- Variable declared without initialization
- Using :=: or :~: on uninitialized return parameter
- Conditional initialization not covering all paths
- Trying to use mutating operator before first assignment
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08020: might be used before being initialised
#!ek9 defines module error.e08020.bad defines function describe() -> ready as Boolean <- rtn as String: "unknown" label as String? if ready label: "ready" rtn: label countOne() <- rtn as Integer: 0 counter as Integer? counter++ rtn: counter
Fixed: Give the variable a value before the paths divide
#!ek9 defines module error.e08020.good defines function describe() -> ready as Boolean <- rtn as String: "unknown" label <- "not ready" if ready label: "ready" rtn: label countOne() <- rtn as Integer: 0 counter <- 0 counter++ rtn: counter
Fixed: Or assign it on every path
#!ek9 defines module error.e08020.good.every.path defines function describe() -> ready as Boolean <- rtn as String: "unknown" label as String? if ready label: "ready" else label: "not ready" rtn: label
Questions and answers
These Q&A entries show E08020 and its fix: