Why can't I use a void function in a stream pipeline in EK9?

← Streams and Pipelines · Ref: Q928

Void functions can't be used in stream pipelines. Streams pass values from stage to stage, and a void function produces nothing to pass along.

STREAM DATA FLOW

Every pipeline stage transforms or filters elements. The output of one stage feeds the next:

  cat items | map with transform | filter by predicate | collect as List of T

If 'transform' returns void, there is nothing for 'filter' to receive.

CORRECT: Function returns a value

  toUpper() as pure
    -> item as String
    <- rtn as String: item.upperCase()
  cat words | map with toUpper | collect as List of String

INCORRECT: Void function in pipeline

  logItem()
    -> item as String
    stdout.println(item)        // returns nothing
  cat words | map with logItem  // ERROR: void produces no output

For side effects, use 'tee' with a collection, or redirect with '> stdout'.

See Q235 for stream operations. See Q866 for void with call. See Q843 for return requirements.

Example

defines module qa.streams.void.not.allowed

  defines function

    toUpper() as pure
      -> item as String
      <- rtn as String: item.upperCase()

  defines program

    StreamVoidDemo()
      stdout <- Stdout()

      //Demonstrate that toUpper returns a value — required for stream pipelines
      uppered <- toUpper("hello")
      stdout.println(`Uppercased: ${uppered}`)

      //A function that returns a value can be used in map
      stdout.println(toUpper("world"))
Other ways to ask this
  • What triggers E10020 in EK9 stream pipelines?
  • Why does map reject my function that returns nothing?
  • Can I use a procedure in a stream pipeline?

Coming from another language?

Java: Stream.map() requires Function<T,R> — Consumer (void) not allowed. Python: map() expects a return value. Rust: iter().map() requires FnMut(T) -> U. Go: no streams. EK9: pipeline stages require value-producing functions.

Keywords: void, produce, pipeline, value, stream, map, E10020, function