Reputation: 11760
I can write
unitlist |> Enum.filter(&(s in &1))
or I can write
for u <- unitlist, s in u, do: u
What is the difference in capabilities of the two constructs?
Upvotes: 4
Views: 737
Reputation: 12127
Like @Dogbert said in his answer: In your example, it is doing the same thing. And for
comprehension can do a lot more than filter. It could easily replace a lot of Enum
functions.
OK so for is much more powerful -- then why does Enum.filter exist? When would you want to use that in place of for?
Imagine asking, "Why drive your 2-door coupe to work when you could drive an RV?" :)
Some of the advantages of the Enum
functions are that they are simpler, better chained with pipes, and can describe your intention better.
e.g.
[1, 2, 3, 4]
|> Enum.filter(&(&1 > 2))
|> Enum.map(&to_string/1)
|> Enum.join()
# "34"
Upvotes: 3
Reputation: 222148
For this particular case they're identical no matter what the value of unitlist
is -- they both accept any Enumerable and run the s in &1
check on each item and return a new list for those returning a truthy value.
for
has many more features than what Enum.filter
can do alone: You can have iterate through multiple enumerables and generate a flat list of results. You can have a fallible pattern on the left of <-
and for
will silently skip over those items instead of throwing an error. You can modify the value returned after the check. The following code snippet demonstrates all this:
iex(1)> for a <- 1..3, b = 2 <- 1..3, a > 1, do: {a, b}
[{2, 2}, {3, 2}]
A for
can be desugared to a combination of Enum.map
, if
, and Enum.flat_map
. The above is the same as this:
Enum.flat_map(1..3, fn a ->
Enum.flat_map(1..3, fn
b = 2 ->
if(a > 1, do: [{a, b}], else: [])
_ ->
[]
end)
end)
|> IO.inspect
Upvotes: 4