How does EK9 enforce variable initialization order?
← Data Flow Safety · Ref: Q688
EK9 tracks variable initialization state through the control flow and rejects any reference to a variable before it has been both declared and initialized.
DECLARATION ORDER (E08010)
Variables must be declared before any reference to them. A forward reference to a variable that has not yet been declared triggers E08010.
INITIALIZATION TRACKING (E08020)
Even after declaration, a variable must be initialized before use. If a variable is declared but not assigned a value before being read, E08020 is triggered.
BRANCH ANALYSIS
The compiler tracks initialization across branches. If a variable is only initialized in one branch of an if/else, the compiler knows it may be uninitialized after the branch.
CORRECT PATTERNS
1. Declare and initialize together: name <- "value"
2. Declare with type and initializer: name as String: "value"
3. Guard-based initialization: if name <- getValue()
See Q632 for define-before-use. See Q633 for init across branches. See Q634 for guard before access.
Example
defines module qa.dataflow.initorder defines function <?- Correct: each variable initialized before use. Sequential computation with proper ordering. -?> calculateShipping() as pure -> itemWeight as Float distanceKm as Float <- shippingCost as Float: 0.0 baseRate <- 5.0 weightFactor <- itemWeight * 0.5 distanceFactor <- distanceKm * 0.1 shippingCost: baseRate + weightFactor + distanceFactor <?- Correct: guard-based initialization. Variable is only used inside the guard where it is guaranteed set. -?> formatWeight() as pure -> weightGrams as Float <- formatted as String: "unknown weight" if weightGrams > 0.0 kilograms <- weightGrams / 1000.0 formatted: `${kilograms} kg` <?- Correct: initialization across all branches. Every branch assigns before later use. -?> classifyTemperature() as pure -> celsius as Float <- classification as String: "moderate" freezingPoint <- 0.0 boilingPoint <- 100.0 if celsius < freezingPoint classification: "freezing" else if celsius > boilingPoint classification: "boiling" defines program VariableInitOrderDemo() stdout <- Stdout() cost <- calculateShipping(2.5, 50.0) stdout.println(`Shipping: ${cost}`) stdout.println(formatWeight(1500.0)) stdout.println(formatWeight(0.0)) stdout.println(classifyTemperature(-5.0)) stdout.println(classifyTemperature(50.0)) stdout.println(classifyTemperature(150.0))
Common mistakes
E08010 — A variable must be declared before any reference to it. Using baseRate before its declaration is a forward reference. See ek9 -h E08010 for details.
Incorrect:
shippingCost: baseRate + weightFactor + distanceFactor baseRate <- 5.0
Correct:
baseRate <- 5.0 weightFactor <- itemWeight * 0.5 distanceFactor <- distanceKm * 0.1 shippingCost: baseRate + weightFactor + distanceFactor
E08050 — A variable must be initialized before use. If classification has no default and is only assigned in one branch, it may be uninitialized when read. See ek9 -h E08050 for details.
Incorrect:
<- classification as String?
Correct:
<- classification as String: "moderate"
Other ways to ask this
- What is E08010 variable used before defined?
- What is E08020 variable used before initialized?
- Does EK9 check that variables are initialized before use?
- What happens if I reference an uninitialized variable?
Coming from another language?
Java: definite assignment analysis, compile error for uninitialized locals. Python: NameError at runtime. JavaScript: var hoisting, undefined. C: undefined behavior. Rust: ownership prevents use of moved values. EK9: compile-time initialization tracking with E08010 and E08020.
Keywords: initialize, forward, data-flow, E08020, declaration, reference, safety, initialization, variable, E08010, order