What is the EK9 equivalent of Python list comprehensions?

← Collections and Data Structures · Ref: Q131

Python list comprehensions translate to EK9 stream pipelines using cat | filter | map | collect. The pipe syntax is explicit about each operation stage.

BASIC FILTERING

Python: [x for x in items if x > 0]
EK9: cat items | filter by isPositive | collect as List of Integer
Define the predicate as a named pure function.

BASIC MAPPING

Python: [f(x) for x in items]
EK9: cat items | map with transform | collect as List of String
Define the transform as a named pure function.

FILTER THEN MAP

Python: [f(x) for x in items if pred(x)]
EK9: cat items | filter by pred | map with transform | collect as List of String
Pipeline stages chain naturally, filter first then map.

REDUCTION

Python: sum(x for x in items if x > 0)
EK9: cat items | filter by isPositive | collect as Integer
collect as Integer sums the stream.

SORT AND LIMIT

Python: sorted(items)[:5]
EK9: cat items | sort | head 5 | collect as List of Integer
head replaces Python's slice notation for taking first N.

NESTED COMPREHENSIONS

Python: [x for sublist in nested for x in sublist]
EK9: cat nested | flatten | collect as List of String
flatten replaces nested for-loops in comprehensions.

See Q89 for basic stream pipelines. See Q120 for sorting. See Q124 for grouping. See Q125 for head/tail/skip.

Example

defines module qa.collections.pythoncomprehensions

  defines function

    isPositive() as pure
      -> num as Integer
      <- rtn as Boolean: num > 0

    doubleIt() as pure
      -> num as Integer
      <- rtn as Integer: num * 2

    intToString() as pure
      -> num as Integer
      <- rtn as String: $num

  defines program

    PythonComprehensionsDemo()
      stdout <- Stdout()

      numbers <- [-2, -1, 0, 1, 2, 3, 4, 5]

      // === FILTERING ===
      // Python: [x for x in numbers if x > 0]

      positives <- cat numbers | filter by isPositive | collect as List of Integer
      stdout.println(`Positives: ${positives}`)

      // === MAPPING ===
      // Python: [x * 2 for x in numbers]

      doubled <- cat numbers | map with doubleIt | collect as List of Integer
      stdout.println(`Doubled: ${doubled}`)

      // === FILTER THEN MAP ===
      // Python: [x * 2 for x in numbers if x > 0]

      doubledPositives <- cat numbers | filter by isPositive | map with doubleIt | collect as List of Integer
      stdout.println(`Doubled positives: ${doubledPositives}`)

      // === REDUCTION ===
      // Python: sum(x for x in numbers if x > 0)

      total <- cat numbers | filter by isPositive | collect as Integer
      stdout.println(`Sum of positives: ${total}`)

      // === SORT AND LIMIT ===
      // Python: sorted(numbers)[:3]

      topThree <- cat numbers | sort | head 3 | collect as List of Integer
      stdout.println(`First 3 sorted: ${topThree}`)

      // === NESTED FLATTEN ===
      // Python: [x for sublist in nested for x in sublist]

      nested <- [["a", "b"], ["c", "d"], ["e", "f"]]
      flat <- cat nested | flatten | collect as List of String
      stdout.println(`Flattened: ${flat}`)

Common mistakes

E50001 — The 'filter by' pipeline stage requires a function that returns Boolean. If the filter function returns Integer instead of Boolean, E50001 is triggered — must return a Boolean. In Python, any truthy value works as a filter. In EK9, the filter function must explicitly return Boolean. See ek9 -h E50001 for details.

Incorrect:

badFilter() as pure
      -> num as Integer
      <- rtn as Integer: num

Correct:

isPositive() as pure
      -> num as Integer
      <- rtn as Boolean: num > 0

E07830 — The collect type must match the pipeline's element type. An Integer pipeline cannot collect into List of String because there is no pipe operator between Integer and String. E07830 is triggered — unable to find a pipe operator for type. In Python, type mismatches fail at runtime. In EK9, the compiler catches them. See ek9 -h E07830 for details.

Incorrect:

cat numbers | filter by isPositive | collect as List of String

Correct:

cat numbers | filter by isPositive | collect as List of Integer

E07830 — The collect type must match the pipeline's element type. An Integer pipeline cannot collect into List of String. See ek9 -h E07830 for details.

Incorrect:

positives <- cat numbers | filter by isPositive | collect as List of String

Correct:

positives <- cat numbers | filter by isPositive | collect as List of Integer

E50060 — EK9 has no .stream() or .map() methods. Use pipe syntax: cat source | map with func | collect as Type. See ek9 -h E50060 for details.

Incorrect:

doubled <- numbers.stream().map(doubleIt).collect()

Correct:

doubled <- cat numbers | map with doubleIt | collect as List of Integer

E07830 — The collect type must match the pipeline's output element type. After map with doubleIt, the stream contains Integer, not String. See ek9 -h E07830 for details.

Incorrect:

doubledPositives <- cat numbers | filter by isPositive | map with doubleIt | collect as List of String

Correct:

doubledPositives <- cat numbers | filter by isPositive | map with doubleIt | collect as List of Integer

E07830 — The collect type must match the pipeline's element type. An Integer pipeline cannot collect into List of String. See ek9 -h E07830 for details.

Incorrect:

topThree <- cat numbers | sort | head 3 | collect as List of String

Correct:

topThree <- cat numbers | sort | head 3 | collect as List of Integer

E50060 — EK9 has no Java-style flatMap() or collect() methods on List. Use | flatten in a pipeline to flatten nested lists. See ek9 -h E50060 for details.

Incorrect:

flat <- nested.flatMap().collect()

Correct:

flat <- cat nested | flatten | collect as List of String

E07830 — The collect type must match the pipeline's element type. A String pipeline cannot collect into List of Integer. See ek9 -h E07830 for details.

Incorrect:

flat <- cat nested | flatten | collect as List of Integer

Correct:

flat <- cat nested | flatten | collect as List of String
Other ways to ask this
  • How do I translate Python list comprehensions to EK9?
  • How do I filter and transform lists in EK9 like Python?
  • What replaces [x for x in list if cond] in EK9?

Coming from another language?

Python: [expr for var in iterable if cond] comprehension syntax, generator expressions with (), dict comprehensions {k: v for ...}. EK9: cat source | filter by pred | map with func | collect as Type pipeline. Key differences: EK9 requires named functions (not lambdas), explicit pipeline stages, strongly typed collection results. Both require the data source first, then operations.

Keywords: equivalent, translate, list, python, stream, filter, comprehension, pipeline, data-structure, collection, migration, map