chx
chx

Reputation: 11760

List comprehension vs Enum.filter

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

Answers (2)

ryanwinchester
ryanwinchester

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

Dogbert
Dogbert

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

Related Questions