Reputation: 1906
I'm a neophyte of Elixir and I'm learning and reading something about list/enum usage and function piping.
I learned how to combine Enum.map
and Enum.each
, e.g. manipulating the content of a list and printing the results list to console through
people = ["Qui", "Quo", "Qua"]
people
|> Enum.map(&String.upcase/1)
|> Enum.map(&Hello.hello/1)
|> Enum.each(&IO.puts/1)
I'm wondering if it exists a library function that combines Enum.map
and Enum.each
together: my idea is to do something for list's each element AND return the untouched list, in order to proceed piping function calls.
Sure, I can add side-effects to the function passed to Enum.map
, but I don't like this approach very much and I would like to keep side effects explicitly separated from functional transformations.
I read Enum
and List
documentation, but I can't figure how do this: Enum.each
returns :ok
and I can't find something similar returning the initial list.
So I implemented it myself as follows:
defmodule MyEnum do
def tee list, action do
Enum.map(list, fn item ->
action.(item)
item
end)
end
end
(disclaimer: sure, I added side effects to map
, but I isolated this dirtyness into a function whose name should clarify my intent) and rewrote the previous example as
people = ["Qui", "Quo", "Qua"]
people
|> Enum.map(&String.upcase/1)
|> Enum.map(&Hello.hello/1)
|> MyEnum.tee(&IO.puts/1)
|> Enum.map(&String.upcase/1)
|> Enum.each(&IO.puts/1)
I works (and It was didactically very useful, for me, to wrote this code), but I'm wondering
Thanks in advance!
Upvotes: 3
Views: 1110
Reputation: 50245
Stream.each will do what you want but you will need to consume the stream to trigger the effects.
Executes the given function for each item.
Useful for adding side effects (like printing) to a stream.
people
|> Enum.map(&String.upcase/1)
|> Stream.each(&IO.inspect/1)
|> Enum.to_list
Upvotes: 3