How do I use streams and stream pipelines in EK9?
← Getting Started · Ref: Q89
EK9 lists use cat | pipe | collect syntax for stream pipelines, replacing Java Streams, Python comprehensions, and JS array methods.
BASIC PATTERN: cat source | operations | terminal
cat numbers | filter by isEven | collect as List of Integer cat numbers | map with doubleIt | collect as List of Integer cat numbers | collect as Integer
FILTER BY
evens <- cat numbers | filter by isEven | collect as List of Integer
Predicate must be pure, returning Boolean.
MAP WITH
doubled <- cat numbers | map with doubleIt | collect as List of Integer
COLLECT AS
List of T collects elements. Integer reduces by summation.
DIRECT OUTPUT
cat numbers | map with intToString > stdout
TEE FOR SIDE EFFECTS
cat numbers | tee in sideEffect | collect as List of Integer
COMBINING: stages chain naturally. Streams replace loops with break/continue (EK9 has none).
See Q45 for List basics. See Q51 for abstract pipeline functions. See Q52 for dynamic functions. See Q53 for closures. See Q54 for Predicate/Comparator/UnaryOperator. See Q55 for delegates. See Q59 for pipelines. See Q64 for for-range. See Q65 for for-in. See Q88 for List operations. See Q120 for sorting. See Q122 for custom collect. See Q124 for group by. See Q125 for head/tail/skip. See Q133 for tee/uniq. See Q235 for stream reference. See Q236 for custom iterators. See Q237 for streams vs loops. See Q265 for fluent API. See Q275 for AI break/continue. See Q284 for first match.
Example
defines module qa.list.streams defines function isEven() as pure -> num as Integer <- rtn as Boolean: num mod 2 == 0 doubleIt() as pure -> num as Integer <- rtn as Integer: num * 2 intToString() as pure -> num as Integer <- rtn as String: $num defines program ListStreamsDemo() stdout <- Stdout() numbers <- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] stdout.println(`Numbers: ${numbers}`) // === FILTER BY === // Select even numbers evens <- cat numbers | filter by isEven | collect as List of Integer stdout.println(`Evens: ${evens}`) // === MAP WITH === // Double each number doubled <- cat numbers | map with doubleIt | collect as List of Integer stdout.println(`Doubled: ${doubled}`) // Transform to strings asStrings <- cat numbers | map with intToString | collect as List of String stdout.println(`As strings: ${asStrings}`) // === COLLECT AS REDUCTION === // Sum all numbers total <- cat numbers | collect as Integer stdout.println(`Sum: ${total}`) // === COMBINED PIPELINE === // Filter then map doubledEvens <- cat numbers | filter by isEven | map with doubleIt | collect as List of Integer stdout.println(`Doubled evens: ${doubledEvens}`) // === DIRECT OUTPUT === // Pipe directly to stdout cat numbers | map with intToString > stdout
Common mistakes
E07520 — The 'filter by' pipeline stage requires a predicate function returning Boolean. A function returning any other type triggers E07520 — filter function must return Boolean. See ek9 -h E07520 for details.
Incorrect:
filter by doubleIt
Correct:
filter by isEven
E07830 — Each pipeline stage must accept the type produced by the previous stage. A type mismatch between stages triggers E07830 — pipeline type mismatch. See ek9 -h E07830 for details.
Incorrect:
map with intToString | collect as List of Integer stdout.println(`As strings: ${asStrings}`)
Correct:
map with intToString | collect as List of String stdout.println(`As strings: ${asStrings}`)
Other ways to ask this
- How do I filter and map a list in EK9?
- What is the cat pipe collect pattern in EK9?
- How do stream pipelines work with lists in EK9?
- What replaces for loops with break in EK9?
- What is the EK9 equivalent of Java Stream API?
Coming from another language?
Java: Stream API, verbose Collectors. Python: list comprehensions. JS: .filter().map().reduce(). Go: manual loops. EK9: cat | filter by | map with | collect as, unified pipe syntax.
Keywords: migrate, start, transform, lazy, async, fluent, sequence, filter, first, parallel, functional, cat, beginner, concurrency, intro, chain, map, stream, pipe, pipeline, collect, tee, stdout