mszmurlo
In comprehensions, why a syntax difference between `into:` and `reduce:`
Recently ‘discovered’ the reduce: option for comprehensions. Very useful, yet there is a syntax difference between into: and reduce: that I don’t understand:
-
into:requires the comprehension’s code block to return the element that is to be inserted into the collection:for x<-0..2, y<-0..3, into: %{} do {{x, y}, x*y} end -
reduce:requires aaccumulator -> codeblockfor x<-0..2, y<-0..3, reduce: %{} do acc -> acc |> Map.put({x, y}, x*y) endThis allows doing multiple modifications to the collections which actually was my use case:
for x<-0..2, y<-0..3, reduce: %{} do acc -> acc |> Map.put({x, y}, x*y) |> Map.put({x+10, y+10}, x*y) end
I was wondering why in the first case we simply return the element to be inserted while in the second case we need a acc -> code(acc) block. I believe it’s for having the possibility to name the accumulator, but is this assumption correct?
I could imagine that for into: we could return a tuple of all the inserts to be done:
for x<-0..2, y<-0..3, into: %{} do
{ {{x, y}, x*y}, {{x+10, y+10}, x*y} }
end
or for reduce: to have a syntax like reduce: {acc_name, acc_initial_value}:
for x<-0..2, y<-0..3, reduce: {acc, %{}} do
acc |> Map.put({x, y}, x*y) |> Map.put({x+10, y+10}, x*y)
end
(I actually never really thought about what acc -> some_code(acc) means. I simply use it because the documentations says so. So I may also need a quick explanation on this topic…)
Most Liked
mudasobwa
Well, I am the one who uses for comprehension if and only if I need a filter (maybe several nested clauses as well, but I don’t realy do numeric calculus often.) Specifically, I love filtering with pattern matching, not the bare x < 0-like filters:
for %{status: :error} = error <- results,
%{origin: :some_cause} <- [error],
do: error.description
YMMV.
mudasobwa
This question is isomorphic to the following one:
Why
Enum.maphas arity 2, butEnum.reducehas arity 3?
One might abuse Enum.reduce/3 for mapping, but the actual difference is reduce is folding, decreasing the dimension of the input. In SQL that’s called aggregation. sum is arguably the most trivial example, receiving a list and producing a scalar. That’s obviously impossible without the accumulator.
LostKobrakai
The reduce syntax mimics the syntax of an anonymous function fn parameter -> body end. The reduce option uses that, because it‘s the only option on for, which gets an extra input beyond what is provided by generators or assignments in the for … do portion - the first parameter to the for special form.
Popular in Thoughts On...
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








