Why must I capture the return value of a pure function call?
← Comparison Patterns · Ref: Q641
EK9 detects when a function with a return value is called as a bare statement and the return value is discarded. For pure functions this is always an error (E11051) because a pure function has no side effects, so calling it without using the result is completely pointless.
DISCARDED RETURN VALUE (E11050)
Calling a function that returns a value without capturing the result:
computeTotal(items) <- discards the returned total
The function was called, but its result was thrown away. This usually means the developer forgot the assignment.
DISCARDED PURE RETURN (E11051)
Calling a pure function as a bare statement is especially bad because pure functions have NO side effects. The call does nothing observable. It is dead code.
DISCARDED CONSTRUCTOR (E11055)
Creating an object without capturing the reference:
Sensor(98.6) <- creates and immediately discards
This is always a bug. If you need side effects, use a function.
DISCARDED RESULT OR OPTIONAL (E11052)
Calling a function that returns Result or Optional and ignoring the result defeats the purpose of these types.
CORRECT PATTERN
Always capture the return value of functions that return values:
total <- computeTotal(items) processed <- transform(input) newList <- List() of String
See Q316 for discarded return detection. See Q640 for collection patterns. See Q635 for pure mutation restrictions.
Example
defines module qa.comparison.capturereturn defines constant SUM_THRESHOLD <- 6 defines function <?- Pure function: its return value MUST be captured. Calling this without capturing triggers E11051. -?> computeSum() as pure -> valueA as Integer valueB as Integer <- total as Integer: valueA + valueB <?- Pure function: return value must be captured. -?> formatPrice() as pure -> price as Float <- formatted as String: `Price: ${price}` <?- Pure function with string processing. -?> buildLabel() as pure -> prefix as String suffix as String <- label as String: `${prefix}-${suffix}` <?- Non-pure function with return value. Return should still be captured (E11050). -?> fetchAndLog() -> itemId as Integer <- itemName as String: `item-${itemId}` defines program CaptureReturnDemo() stdout <- Stdout() //Correct: capture the return value total <- computeSum(10, 20) stdout.println(`Sum: ${total}`) //Correct: capture formatted string priceStr <- formatPrice(9.99) stdout.println(priceStr) //Correct: capture and use label <- buildLabel("order", "001") stdout.println(label) //Correct: capture non-pure return itemName <- fetchAndLog(42) stdout.println(`Fetched: ${itemName}`) //Correct: use return value directly in expression doubled <- computeSum(5, 5) * 2 stdout.println(`Doubled: ${doubled}`) //Correct: use in condition if computeSum(3, 4) > SUM_THRESHOLD stdout.println("Sum exceeds threshold")
Common mistakes
E50001 — Removing the variable declaration means later references to the variable become unresolved, triggering E50001. See ek9 -h E50001 for details.
Incorrect:
computeSum(10, 20)
Correct:
total <- computeSum(10, 20)
E50001 — Removing the variable declaration means later references to the variable become unresolved, triggering E50001. See ek9 -h E50001 for details.
Incorrect:
formatPrice(9.99)
Correct:
priceStr <- formatPrice(9.99)
Other ways to ask this
- What is E11050 discarded return value?
- What is E11051 discarded pure function return?
- Why does EK9 reject calling a function without capturing its result?
Coming from another language?
Java: return values can always be silently discarded, no warning by default. IntelliJ warns on discarded return from pure-annotated methods (optional). Rust: #[must_use] attribute warns when return value is discarded (opt-in). Go: error return values often silently discarded (common bug source). Kotlin: no enforcement. C++: [[nodiscard]] attribute (C++17, opt-in). EK9: mandatory compiler error E11050/E11051 for discarded return values, especially pure functions.
Keywords: immutable, return, side-effect, discard, E11055, comparison, E11052, E11051, E11050, result, constructor, compare, function, pattern, capture, ok, dead, error, pure, guard