Elixir allows you to use Stream
s instead of Enum
s to prevent intermediary copies of collections. But when you're on the last step, would it even matter?
Even when you get to the smallest details isn't this
Stream.concat(header, rows)
|> CSV.encode
|> Stream.into(output)
|> Stream.run
the same as this?
Stream.concat(header, rows)
|> CSV.encode
|> Enum.into(output)
If so, why would the Stream.into/3
docs advocate the pairing of Stream.into
+ Stream.run
and not just say Enum.into
?
Perhaps it's a simple as just being more readable and discoverable.
Your two examples don't really do the same thing. The first one just runs the stream pipeline, while the second one will also give you a return value. Since you are not using the result, Stream.run
is just fine in this case.
Generally, if you're interested in the result of a stream you can always use the Enum
counterparts in the last step of a pipeline. Stream.run
will not return the results, but rather apply the pipeline and then return :ok
. This is useful if you're interested in the side effects rather than the actual return value.
I suppose the reason we have Stream.into
as well is that it might not actually be the last step in the pipeline. Here's a contrived example:
output = IO.stream(:stdio, :line)
Stream.iterate(0, &(&1 + 1))
|> Stream.chunk(2, 1)
|> Stream.into(output, &"BEFORE: #{inspect &1}\n")
|> Stream.map(fn [x, y] -> x * y end)
|> Stream.into(output, &"AFTER: #{inspect &1}\n")
|> Stream.take(3)
|> Stream.run
Which will output
BEFORE: [0, 1]
AFTER: 0
BEFORE: [1, 2]
AFTER: 2
BEFORE: [2, 3]
AFTER: 6
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With