Why must operator and pure function return values be captured?
← Code Quality · Ref: Q693
EK9 requires that return values from constructors, operators, pure functions, and Result-producing functions are captured in variables. Discarding these values indicates a bug.
CONSTRUCTOR RETURNS (E11055)
A constructor creates an object. Calling a constructor as a bare statement discards the result immediately. This is always either a bug (forgot the assignment) or a misuse of constructors for side effects:
Sensor(98.6) // E11055: constructor result discarded sensor <- Sensor(98.6) // Correct: captured
OPERATOR RETURNS (E11050)
Operators like + and * always produce new values. Discarding an operator result means the computation was pointless:
name + " suffix" // E11050: result discarded combined <- name + " suffix" // Correct: captured
PURE FUNCTION RETURNS (E11051)
Pure functions have no side effects. If the return value is discarded, the call accomplished nothing:
validate(input) // E11051: pure result discarded isValid <- validate(input) // Correct: captured
RESULT RETURNS (E11052)
Result-producing functions may fail. Discarding the Result ignores potential errors:
parseAge(text) // E11052: Result discarded result <- parseAge(text) // Correct: captured
See Q310 for code quality overview. See Q316 for discarded returns detail. See Q321 for naming conventions.
See Q732 for discarded return boundary examples.
Example
defines module qa.codequality.capturedreturns defines function <?- Pure function: return value must be captured. Discarding a pure return is always a bug. -?> sanitizeInput() as pure -> rawInput as String <- cleaned as String: rawInput.trim() <?- Another pure function in the chain. -?> validateLength() as pure -> inputText as String <- isValid as Boolean: length inputText > 0 defines class <?- Class demonstrating correct return value capture. Every operator and pure return is stored in a variable. -?> TextBuffer content <- String() TextBuffer() -> initialContent as String this.content: initialContent getContent() as pure <- rtn as String: content append() -> suffix as String content: content + suffix default operator ? defines program CapturedOperatorReturnsDemo() stdout <- Stdout() //Correct: pure function return captured cleaned <- sanitizeInput(" hello ") stdout.println(cleaned) //Correct: pure function return captured isValid <- validateLength(cleaned) stdout.println(`Valid: ${isValid}`) //Correct: operator return captured combined <- cleaned + " world" stdout.println(combined) //Correct: method return captured textStore <- TextBuffer("start") storeContent <- textStore.getContent() stdout.println(storeContent)
Common mistakes
E50060 — String has no toUpperCase() method in EK9. Use upperCase() instead. See ek9 -h E50060 for details.
Incorrect:
stdout.println(cleaned.toUpperCase())
Correct:
stdout.println(cleaned)
E50060 — String has no toUpperCase() method in EK9. Use upperCase() instead. See ek9 -h E50060 for details.
Incorrect:
combined <- cleaned.toUpperCase() + " world"
Correct:
combined <- cleaned + " world"
E50001 — Removing the variable declaration means later references to the variable become unresolved, triggering E50001. See ek9 -h E50001 for details.
Incorrect:
sanitizeInput(" hello ")
Correct:
cleaned <- sanitizeInput(" hello ")
E50001 — The pure method getContent returns a value that must be captured. Discarding a pure return is always a bug. See ek9 -h E50001 for details.
Incorrect:
textStore.getContent()
Correct:
storeContent <- textStore.getContent()
Other ways to ask this
- What is E11050 uncaptured operator return?
- What is E11051 uncaptured pure function return?
- What is E11052 uncaptured Result return?
- Why does EK9 require capturing return values?
Coming from another language?
Java: return values can be silently discarded. Rust: #[must_use] annotation (optional). Go: blank identifier _ explicitly discards. Python: no enforcement. C++: [[nodiscard]] attribute (optional). EK9: all operator, pure, and Result returns must be captured (compile error, not warning).
Keywords: discard, return, quality, operator, constructor, E11055, E11052, E11051, E11050, pure, capture, metric, side-effect, immutable, Result, function, clean-code