I just upgrade OTP to 20.0 and elixir to 1.5.0-rc.1, I got warnings on usage of filter_map. Why is it deprecated?
Changelog for 1.5 says:
[Enum] Deprecate Enum.filter_map/3 in favor of Enum.filter/2 + Enum.map/2 or for-comprehensions
Yes, âfilter+mapâ or âforâ works, but I want to know the reason behind it.
I think the reason was the fact that it was an outlier. The only âfusedâ function.
Enum.map_join
= Enum.map
+ Enum.join
Enum.flat_map
= Enum.map
+ Enum.concat
Can someone help a rookie (me) understand the
[âŠ] or for comprehensions
component of this deprecation message?
Parsing the English can be odd, but theyâre these things, covered in the Guide https://elixir-lang.org/getting-started/comprehensions.html
for comprehensions consist of generators and filters, though the filters seem to be less widely known
Here is an example of using comprehension in lieu of Enum.filter_map/3
:
# filter even numbers
filter_fn = fn n ->
rem(n, 2) == 0
end
# double
map_fn = fn n ->
n * 2
end
some_enum = 1..20
# filter_map version
Enum.filter_map(some_enum, filter_fn, map_fn)
# comprehension version
for n <- some_enum, filter_fn.(n), do: map_fn.(n)
What about flat_map
, flat_map_reduce
, map_reduce
, map_join
and the rest of the âfusedâ function?
Most of them are useful as a way to avoid walking a long list twice.
If you fear multi walks, then use the appropriate Stream
functions.
So the flat_map
, flat_map_reduce
, map_reduce
and map_join
style Enum
functions is just a legacy implementation? They donât give us anything extra, they just help us avoid some extra code for some common use-cases?
Technically flat_map
, like reduce
are considered base-most enumeration functions. flat_map
is the base-most that always returns another enumeration, and reduce
is the base-most that returns anything. filter_map
is pretty duplicative as I always use flat_map
anyways.
thanks!
[1, 2, 3]
|> Enum.map(&(&1+3))
|> Enum.reject(&(&1==4))
# => [5, 6]
=>
[1, 2, 3]
|> Enum.flat_map(fn n ->
case n+3 do
4 -> []
n -> [n]
end
end)
# => [5, 6]
Hello from the future. The commit log doesnât mention why it was deprecated, but whatyouhide, a core team member, explained a bit on this issue:
Elixir deprecated the usage of
Enum.filter_map/3
because it was counterintuitive and the same could be achieved withEnum.filter/2
+Enum.map/2
, withStream
, or with afor
comprehension.
And also José Valim in the mailing list:
I would use comprehensions:
for item <- 1, 2, 3, rem(item, 2) == 0, do: item * 2
There is no reason for Enum.filter_map or Enum.map_filter to exist besides backwards compatibility.