Proposal: `Enum.filter_map/2`

94 views
Skip to first unread message

Łukasz Niemier

unread,
Apr 26, 2017, 6:42:11 AM4/26/17
to elixir-lang-core
In current form `Enum.filter_map/3` isn't always suitable as sometimes we want to first filter then map and sometimes other way around. This is where my proposal comes in that will allow both of these behaviours be available at almost no cost in the same method:

Enum.filter_map([1,2,3], fn item ->
 
if item % 2 == 0 do
   
{:keep, item * 2}
 
else
   
:ignore
 
end
end)

This form is IMHO more readable, as it explicitly states the order of filter and map. This design is based on Rust's std::tier::Iterator::filter_map, however as Elixir doesn't have sum types I needed to use some form of tuple/atom workaround.

Andrea Leopardi

unread,
Apr 26, 2017, 6:44:15 AM4/26/17
to elixir-lang-core
I tend to use Enum.flat_map/2 for that and return [element] instead of {:keep, _} and [] instead of :ignore. It may be a bit slower because of the flattening, but it's never been the bottleneck (or even noticeable) in any code I wrote.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/053143ce-efec-44f3-8e44-45bc36b90a67%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Łukasz Niemier

unread,
Apr 26, 2017, 6:58:00 AM4/26/17
to elixir-lang-core
Alternatively we can change return value to always be tuple in form `{boolean(), any()}` where first value describe value of the `filter` and second is mapping.

Enum.filter_map([1,2,3], fn item ->

 
{
item % 2 == 0, item * 2}
end) # => [4]


However I find such form a little less readable and more error prone.

José Valim

unread,
Apr 26, 2017, 7:10:43 AM4/26/17
to elixir-l...@googlegroups.com
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.

José Valim
Skype: jv.ptec
Founder and Director of R&D

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages