Why does EK9 reject discarded operator return values?

← Code Quality · Ref: Q777

EK9 distinguishes between mutating operators (which change state) and computational operators (which return new values). If you call a computational operator and discard the result, the computation was pointless — dead code.

MUTATING OPERATORS (return Void — side-effect IS the purpose)

  price += tax      // Modifies price in place
  count++           // Increments count
  target :=: source // Copies source into target

COMPUTATIONAL OPERATORS (return values — the VALUE is the purpose)

  total <- price + tax    // Must capture the result
  isEqual <- a == b       // Must use the Boolean
  len <- length name      // Must use the Integer

THIS EXAMPLE

The ShowCalculation program captures the result of Calculator.add, a pure method. The mutation removes the capture, leaving a bare pure-method call that discards its result. That is E11051, the method-call sibling of E11050 (which is raised for a discarded operator call such as 'price.+(tax)'); the principle is the same: a pure call whose result is thrown away is dead code.

See Q238 for operator overview. See Q239 for comparison operators. See Q310 for code quality checks.

Example

#!ek9
defines module qa.codequality.discardedreturn

  defines class

    Calculator

      add() as pure
        ->
          left as Float
          right as Float
        <- rtn as Float: left + right

      multiply() as pure
        ->
          left as Float
          right as Float
        <- rtn as Float: left * right

      default operator ?

  defines program

    ShowCalculation()
      stdout <- Stdout()
      calculator <- Calculator()
      total <- calculator.add(100.0, 15.0)
      stdout.println($total)

Common mistakes

E11051 — Calling a pure method that returns a value and discarding the result is dead code. The method has no side effects, so without capturing the return value the call achieves nothing. See ek9 -h E11051 for details.

Incorrect:

      calculator.add(100.0, 15.0)
      stdout.println("done")

Correct:

      total <- calculator.add(100.0, 15.0)
      stdout.println($total)
Other ways to ask this
  • What triggers E11050 discarded operator return?
  • Why must I capture the result of an operator?
  • What is the difference between += and + in EK9?

Coming from another language?

Java: silently discards return values of any expression statement. Python: silently discards return values. Rust: warns about unused results with #[must_use]. Go: compile error for unused function returns but not operators. Kotlin: no enforcement. EK9: compile error for discarded computational operator returns — dead code is not allowed.

Keywords: E11050, capture, code, computational, dead, discarded, mutating, operator, result, return