ddombrow
Missing something with Stream to Enum
Missing something when going through the Little Elixir book. Made my own function to grab a csv and make weather requests.
The result is the result of the first operation (a correct temperature response from a service, followed by the cities list. I expected a list of outputs only. Any pointers?
def get_cities_weather(csv_path) do
alias NimbleCSV.RFC4180, as: CSV
cities = csv_path
|> File.stream!
|> CSV.parse_stream
|> Stream.map(fn [city, city_ascii, lat, lng, pop, country, iso2, iso3, province] ->
%{name: city_ascii, lat: lat, lng: lng}
end)
cities
|> Enum.map_every(500, fn city ->
Metex.Worker.temperature_of(city)
end)
end
Produces:
[{:ok, 40.8}, %{lat: "34.5167011", lng: "65.25000063", name: "Chaghcharan"},
%{lat: "31.58299802", lng: "64.35999955", name: "Lashkar Gah"},
%{lat: "31.11200108", lng: "61.88699752", name: "Zaranj"},
%{lat: "32.63329815", lng: "65.86669865", name: "Tarin Kowt"},
%{lat: "32.85000016", lng: "68.41670453", name: "Zareh Sharan"}...]
Marked As Solved
NobbZ
If you want that behaviour, you probably want Enum.take_every/2 or Stream.take_every/2.
It could look like this then:
def get_cities_weather(csv_path) do
alias NimbleCSV.RFC4180, as: CSV
csv_path
|> File.stream!
|> CSV.parse_stream
|> Stream.map(fn [city, city_ascii, lat, lng, pop, country, iso2, iso3, province] ->
%{name: city_ascii, lat: lat, lng: lng}
end)
|> Stream.take_every(500)
|> Enum.map(fn city ->
Metex.Worker.temperature_of(city)
end)
end
Also Liked
benwilson512
or use it as an Enumerable
Minor nitpick: Enumerables are neither lazy nor eager. Stream deals with Enumerables lazily, and Enum deals with them eagerly.
So a stream does nothing until it is consumed. It can be consumed by Stream.run or any of the Enum functions that eagerly consume their inputs.
NobbZ
But an important one! I thought if enumerable is the right word here quite a moment. Names are hard especially if you have to deal an remember the relations between similar names.
NobbZ
map_every(enumerable, nth, fun)
map_every(t, non_neg_integer, (element -> any)) :: listReturns a list of results of invoking fun on every nth item of enumerable, starting with the first element.
So you have to wait another 495 elements after the ellipsis, before you will get a processed item again.
Perhaps you want plain old Enum.map/2 or Stream.map/2 instead?








