Elixir allows you to use Streams instead of Enums 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