How to implement Stream.split_with/2?

Enum.split_with/2 splits an enumerable into two lists based on the return value of a function. I would like to know if it is possible to do the same with a stream and get two streams instead of getting two lists and consuming the whole stream. In other words, how could I implement a Stream.split_with/2 function ?

iex(1)> 1..10 |> Stream.map(&(&1)) |> Enum.split_with(fn x -> Integer.mod(x,2) == 0 end)
{[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]}

iex(1)> 1..10 |> Stream.map(&(&1)) |> Stream.split_with(fn x -> Integer.mod(x,2) == 0 end)
{#Stream<...>, #Stream<...>}

You cannot split (any possible) stream without enumeration. Take e.g. File.stream!, which is essentially a file cursor continuously advanced. You cannot magically make those two file cursors.

1 Like

In order to be able to split a stream, since the 2 resulting streams can be consumed asynchronously, you’d need storage to buffer the elements from the original stream. See this: add Stream.split(collection, count) ⇒ {splitted_values, rest_of_stream} · Issue #2922 · elixir-lang/elixir · GitHub

1 Like