They have the same (or equivalent) typespecs:
each(Enumerable.t(), (element() -> term())) :: Enumerable.t()
map(Enumerable.t(), (element() -> any())) :: Enumerable.t()
The types term and any are equivalent per the docs:
The docs don't point out any obvious differences, beyond the intended/expected usage (each/2 mentions side effects):
For simple examples they seem equivalent:
iex(5)> Stream.each( [1, 2, 3], &(&1) ) |> Enum.to_list()
[1, 2, 3]
iex(8)> Stream.map( [1, 2, 3], &(&1) ) |> Enum.to_list()
[1, 2, 3]
The example in the docs for each/2 also seems to work fine with map/2:
iex(9)> stream = Stream.map([1, 2, 3], fn x -> send(self(), x) end)
#Stream<[enum: [1, 2, 3], funs: [#Function<48.50989570/1 in Stream.map/2>]]>
iex(10)> Enum.to_list(stream)
[1, 2, 3]
iex(11)> receive do: (x when is_integer(x) -> x)
1
iex(12)> receive do: (x when is_integer(x) -> x)
2
iex(13)> receive do: (x when is_integer(x) -> x)
3
If Stream.each/2 and Stream.map/2 ARE different – which I'm guessing they are – what is a simple example demonstrating those differences (that could be easily run in iex)? Do they differ in less obvious (e.g. harder to demonstrate) ways as well?