lud
How to halt stream while returning a last value
Hello,
I have this example where I would like a stream transformation to return the whole input list up to the third atom, included.
input = ["a", "b", "c", "d", :x, :y, "e", "f", :z, "g", "h", "i", :aa, :bb, "j"]
Expected output:
["a", "b", "c", "d", :x, :y, "e", "f", :z]
All I can do for now is to return:
["a", "b", "c", "d", :x, :y, "e", "f"]
Of course it would be very easy without the constraint: Further elements from the stream should not be processed once the final atom is found in the stream.
Do you know how I should do that?
Thank you!
Some test code:
defmodule Demo do
def run do
input = ["a", "b", "c", "d", :x, :y, "e", "f", :z, "g", "h", "i", :aa, :bb, "j"]
wanted_atoms = 3
input
#
# Classifier function. In real application it costs money to run so we never
# want to call it if we are not going to process its result.
|> Stream.map(fn
"g" -> raise ~s(should not process "g")
value when is_atom(value) -> {:atom, value}
value -> {:other, value}
end)
# Take 3 atoms if we find them in the stream, take the whole stream
# otherwise.
|> Stream.transform(
_start_fun = fn -> 0 end,
_redux_fun = fn
{:atom, value}, atom_count when atom_count == wanted_atoms - 1 -> {:halt, {:last, value}}
{:atom, value}, atom_count -> {[value], atom_count + 1}
{:other, value}, atom_count -> {[value], atom_count}
end,
__last_fun = fn
# Not called when the reducer returns :halt
{:last, value} -> {[value], nil}
n when is_integer(n) -> {:halt, nil}
end,
_after_fun = fn acc -> :ok end
)
|> Enum.to_list()
|> IO.inspect(limit: :infinity, label: "final")
end
defp get_score(2), do: {:ok, 1234}
defp get_score(_), do: {:error, :nope}
end
Demo.run()
Marked As Solved
al2o3cr
You can do it with a sentinel value, since each step of Stream.transform can emit multiple results:
|> Stream.transform(
fn -> 0 end,
fn
{:atom, a}, atom_count when atom_count+1 < wanted_atoms ->
{[a], atom_count+1}
{:atom, a}, _atom_count ->
{[a, :__no_more_atoms], :ok}
{_, v}, atom_count ->
{[v], atom_count}
end,
fn _ -> :ok end
)
|> Stream.take_while(& &1 != :__no_more_atoms)
The transform produces a stream with an extra value on the end when the last wanted atom is seen, then take_while snips it off and terminates the stream.
5
Also Liked
benwilson512
Author of Craft GraphQL APIs in Elixir with Absinthe
I have also used Stream.concat for this eg. Stream.concat(other_stream, [:ending_value])
2
Popular in Questions
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
What is the idiomatic way of matching for not nil in Elixir?
E.g.,
First way:
defp halt_if_not_signed_in(conn, signed_in_account) when...
New
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set?
Thanks.
New
Hi,
I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
Hello everybody,
usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: )
Hello all, this is ...
New
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors:
[WARN] - (starship::utils): Executing command ...
New
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir
iex(2)...
New
Other popular topics
Hello, I get Persian date from my client and convert it to normal calendar like this:
def jalali_string_to_miladi_english_number(persi...
New
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
Hi there,
I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
I have an umbrella app.
Some of the apps inside depend on other apps in the umbrella, unsurprisingly.
I'm writing a test for one of t...
New
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
Hi,
I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
Hi guys, i’m new in the Elixir world, and i have to say, that i love it!
i’m having some problem to understand anonymous functions with ...
New
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
I am trying to run a deploy with docker and I successfully runned with this command:
docker build -t romenigld/blog-prod .
but when I t...
New
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New







