When should I use a stream pipeline instead of a loop in EK9?

← Streams and Pipelines · Ref: Q1017

Use a stream pipeline when you are filtering, transforming, or collecting items. Use a loop when you need mutation or sequential state between iterations.

LOOP PATTERN → STREAM REPLACEMENT:

Filter and collect:

  LOOP: for item in items / if condition / results += item
  STREAM: cat items | filter by condition | collect as List of T

Transform all items:

  LOOP: for item in items / transformed += convert(item)
  STREAM: cat items | map with convert | collect as List of T

Find first N matching:

  LOOP: for item in items / if condition / results += item / if count >= limit / (no break in EK9)
  STREAM: cat items | filter by condition | head N | collect as List of T

The stream version is shorter, clearer in intent, and the head operation replaces the break pattern naturally.

Example

defines module qa.streams.replacesloop

  defines function

    isHighValue() as pure
      -> amount as Float
      <- rtn as Boolean?

      threshold <- 50.0
      rtn: amount > threshold

    formatAmount() as pure
      -> amount as Float
      <- rtn as String: `Amount: ${amount}`

  defines program

    StreamReplacesLoopDemo()
      stdout <- Stdout()

      amounts <- [12.50, 75.00, 8.99, 120.00, 45.00, 89.99]

      //Stream: filter high values and format
      stdout.println("High value items:")
      cat amounts
        | filter by isHighValue
        | map with formatAmount
        > stdout

      //Stream: collect into new list
      highAmounts <- cat amounts
        | filter by isHighValue
        | collect as List of Float
      stdout.println(`Count: ${highAmounts.length()}`)

Common mistakes

E50060 — EK9 List has no .append() method — add elements with the += operator or build the list via a stream pipeline. See ek9 -h E50060 for details.

Incorrect:

      stdout.println(`Count: ${highAmounts.length()}`)
      highAmounts.append(89.99)

Correct:

      stdout.println(`Count: ${highAmounts.length()}`)
Other ways to ask this
  • How do I replace a for loop with a stream pipeline?
  • What loop patterns should be rewritten as streams in EK9?
  • Show me a loop and its stream equivalent side by side

Coming from another language?

EK9 streams replace filter+collect loop patterns. The stream states intent (filter, transform, limit) while the loop describes mechanism (iterate, check, accumulate).

Keywords: loop, replace, stream, filter, collect, refactor