I usually avoided comprehensions because they felt like an odd part of Elixir syntax. But more complex nested data transformations can get verbose and the the article shows the difference in favor of comprehensions that makes me wanna try them more often. I could think of cases where it would make my code leaner and more readable, but not before it clicked for me.
Most important part is they're expressions so you can mix and match them with function calls
Anyway, bookmarking the article because it's the best explainer of this feature I recall and will gladly pass it to others :)
I have been using elixir for my own projects for a while and I also have not leaned into comprehensions enough. This article has helped me see that blind spot. Bookmarked
Interesting, I use `map` all the time and `for` rarely. I'm not necessarily disagreeing with you as I see this as more of a style preference.
The map approach feels a lot more functional to me and is easy to chain. The `for` method feels a bit awkward. But that said I much prefer Ruby to Python. If I had the opposite preference, I'd probably like the `for` in Elixir more.
I agree with you: I prefer map and reduce unless I specifically need a comprehension because of multiple input collections. IMO for with many conditions etc. becomes too hard to understand, and you have to keep too many things in mind vs. a filter |> map. Regardless, I don't mind its presence, and it definitely has come in handy at times. Yet another reason to enjoy Elixir's approach to language design!
I also use ‘for’ rarely. It silently ignore list elements that don’t match, whereas ‘map’ or ‘each’ blow up. Generally I prefer things to blow up rather than fail silently.
Similar, but different in subtle ways when you get beyond the toy example posted here...particularly that it's always iterating a collection, vs being able to just arbitrarily loop based on arbitrary conditions..where you'd be able to easily break out of it, modify a mutable collection within it etc
I tend to replace most instances of Enum.map with filters. Filters are also easier to read than quite a few instances of Enum.filter or Enum.into, too!
Outside of things like generating a game board, or some other well structured n-dimensional struct, I generally avoid nesting them, though. I’ll use Enum on the outer function(s) and filter for the inner one.
Somehow `for` doesn't read as comprehension to me. In Erlang I used to use comprehensions extensively. In Elixir I almost never do, and only use Enum.map
The bitstring example is a really great use case for parsing binary protocols. I've been looking at implementing QUIC in Elixir/Erlang and I'll be taking a look at this for parsing the packets coming in off the wire.
I think comprehensions make a little bit more sense in the Erlang world than in the Elixir one, just because of the more functional style. Still, I don't think there's anything wrong with them in Elixir either; just a bit odd in context, like a nice wood-grain-veneer MP3 player.
> I think comprehensions make a little bit more sense in the Erlang world
They make a ton of sense (way more than they do for Erlang) in the context of EEx, which is part of the standard Elixir distribution, and a first class part of the language
I'm not the one you asked but elixir's heavy use of piping data through a series of functions is a hallmark of a certain approach to functional programming. It's not "more functional" since that doesn't really make sense per se, but for a lot of people when they think of FP this is the fundamental orientation they have in mind, rather than like function composition or whatever.
Erlang doesn't have a first class pipe macro or special form I don't think, and its standard library isn't built with this in mind, with consistent data-first argument order. So again it's not "less functional" but it doesn't much use one of the most recognizable idioms of functional programming and the only uniquely functional one many people may be familiar with.
I don't know if this is what they meant but it makes sense to me. In elixir piping streams is an ergonomic and similarly performant solution, with the tradeoffs discussed in the article. There's a lot of use case overlap. If the language didn't have comprehensions it wouldn't be very painful for most people, I don't think. Where erlang without them would be a pain in the ass it really has no other general purpose tool for this.
I interpreted their message as saying Erlang is more functional than Elixir, which didn't really make sense to me personally. (I think they are both the same amount of "functional")
Most important part is they're expressions so you can mix and match them with function calls
Anyway, bookmarking the article because it's the best explainer of this feature I recall and will gladly pass it to others :)