Why does EK9 report E11018 for an unused captured variable in a dynamic function?
← Code Quality · Ref: Q1338
EK9 dynamic functions capture variables EXPLICITLY, listing each one in parentheses before the 'is' keyword. Because capture is explicit and by value, every captured variable represents a deliberate dependency that is copied into the closure. If a captured variable is never referenced inside the function body, that capture is dead weight: it adds an unnecessary dependency, copies a value for no reason, and signals a copy-paste or refactoring mistake. EK9 raises E11018 (unused captured variable) at compile time.
The fix is to remove the unused variable from the capture list. Keep only the variables the body actually reads. If you genuinely need the value later, use it in the body; otherwise drop it from the capture list entirely.
This sits alongside E08090 (unused local variable) and E08091 (unused parameter): EK9 treats unused captures, locals, and parameters all as compile-time errors so that declared dependencies and real usage never drift apart.
See Q53 for closure capture mechanics. See Q319 for unused closure capture detection. See Q311 for quality checks.
Example
defines module qa.gettingStarted.unusedCapture defines function mathOperation() as pure abstract -> x as Float y as Float <- result as Float? defines program UnusedCaptureDemo() stdout <- Stdout() //THE FIX: capture ONLY the variables the body actually uses. //'factor' is read inside the body, so it belongs in the capture list. factor <- 10.0 scaled <- (factor) is mathOperation as pure function result:=? x * factor + y stdout.println(`captured: ${scaled(3.0, 1.0)}`) //A value that is NOT needed by the body must NOT appear in the capture //list. Here 'offset' is used, so it is captured; nothing surplus is. offset <- 5.0 biased <- (offset) is mathOperation as pure (result:=? x + y + offset) stdout.println(`biased: ${biased(1.0, 2.0)}`)
Common mistakes
E11018 — The capture list includes 'unused', but the body only reads 'factor', 'x' and 'y'. An explicitly captured variable that the function body never references is dead weight - an unnecessary by-value copy and a false dependency - so EK9 raises E11018. Remove the unused entry from the capture list, keeping only the variables the body actually uses. See ek9 -h E11018 for details.
Incorrect:
scaled <- (factor, stdout) is mathOperation as pure function result:=? x * factor + y
Correct:
scaled <- (factor) is mathOperation as pure function result:=? x * factor + y
Other ways to ask this
- What triggers E11018 unused captured variable?
- Why must every variable I capture in a closure be used in the body?
- How do I fix an unused capture in a dynamic function?
Coming from another language?
Java/Kotlin/JavaScript/Python: capture is implicit and unchecked - a lambda silently closes over any enclosing variable it references, and there is no notion of an 'unused capture' because nothing is captured unless referenced. The dual risk is accidental capture of large objects (memory leaks) with no compiler signal. EK9: capture is an EXPLICIT list, so an entry that the body never uses is unambiguously a mistake and is rejected at compile time via E11018, keeping the declared dependency set exactly equal to the used set.
Keywords: unused, capture, E11018, quality, dynamic, closure, dependency, function