How does EK9 ensure variables are used only after they are defined?
← Data Flow Safety · Ref: Q632
EK9 enforces sequential definition order within a scope. A variable must be declared before any reference to it. This prevents an entire category of bugs where code accidentally references a variable that does not yet exist.
DEFINITION ORDER RULE
Within a function, method, or program body, statements execute top-to-bottom. A variable declared on line 10 cannot be referenced on line 8. The compiler checks this and raises E08010 if the reference precedes the declaration.
WHY THIS MATTERS
Forward references to variables are a common copy-paste error. A developer moves a block of code above its variable declarations and the program silently reads uninitialized memory (in C) or gets undefined (in JavaScript). EK9 eliminates this by making definition order a compile-time guarantee.
EXCEPTIONS
Types and functions can be forward-referenced because EK9 resolves them in a separate phase. Only local variables, parameters, and fields follow strict sequential order.
CORRECT PATTERN
Declare each variable before using it. Group related declarations near their first use. The compiler verifies every reference has a preceding declaration in the same or enclosing scope.
See Q633 for initialization tracking across branches. See Q251 for debugging unset variable errors.
See Q688 for variable init order. See Q692 for field initialization.
Example
defines module qa.dataflow.definitionorder defines function <?- Correct: each variable is declared before it is used. taxRate is declared before taxAmount references it. -?> computeTotal() as pure -> basePrice as Float <- total as Float: basePrice taxRate <- 0.15 taxAmount <- basePrice * taxRate total: basePrice + taxAmount <?- Correct: intermediate results are computed in order. Each step uses only previously declared variables. -?> computeDiscount() as pure -> originalPrice as Float discountPercent as Float <- finalPrice as Float: originalPrice discountFraction <- discountPercent / 100.0 discountAmount <- originalPrice * discountFraction finalPrice: originalPrice - discountAmount <?- Correct: variables defined in sequence, each referencing only previously declared values. -?> buildGreeting() as pure -> firstName as String lastName as String <- greeting as String: firstName fullName <- `${firstName} ${lastName}` greeting: `Hello ${fullName}, welcome` defines program DefineBeforeUseDemo() stdout <- Stdout() totalPrice <- computeTotal(100.0) stdout.println(`Total: ${totalPrice}`) discounted <- computeDiscount(200.0, 15.0) stdout.println(`Discounted: ${discounted}`) msg <- buildGreeting("Alice", "Smith") stdout.println(msg)
Common mistakes
E08010 — Referencing taxRate before it is declared is a forward reference error. Variables must be declared before use. See ek9 -h E08010 for details.
Incorrect:
taxAmount <- basePrice * taxRate taxRate <- 0.15
Correct:
taxRate <- 0.15 taxAmount <- basePrice * taxRate
E50001 — Removing the variable declaration means later references to the variable become unresolved, triggering E50001. See ek9 -h E50001 for details.
Incorrect:
computeTotal(100.0)
Correct:
totalPrice <- computeTotal(100.0)
Other ways to ask this
- What happens if I use a variable before declaring it?
- Does EK9 check declaration order?
- What is E08010 used before defined?
Coming from another language?
Java: variables must be declared before use (compiler error). JavaScript: var hoisting allows use before declaration (reads as undefined). Python: NameError at runtime if variable not yet assigned. C: undefined behavior if variable not initialized. Go: compile error for undeclared variable. Rust: compile error for uninitialized variable. EK9: compile error E08010 for any reference before declaration, enforced at Phase 3.
Keywords: define, scope, before, forward, order, E08010, safety, initialize, migrate, reference, data-flow, declaration, use, variable