mszmurlo

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 a accumulator -> code block

    for x<-0..2, y<-0..3, reduce: %{} do 
      acc -> acc |> Map.put({x, y}, x*y)
    end
    

    This 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

mudasobwa

Creator of Cure

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

mudasobwa

Creator of Cure

This question is isomorphic to the following one:

Why Enum.map has arity 2, but Enum.reduce has 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

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.

Where Next?

Popular in Thoughts On... Top

pera
Releases is a fantastic new feature in Elixir 1.9, but it comes with one important caveat: Once a release is assembled, it can be packa...
New
W3NDO
I went back to building on ruby during an interview and I was asked to explain symbols. It got me thinking about ruby symbols and elixir ...
New
mszmurlo
Recently ‘discovered’ the reduce: option for comprehensions. Very useful, yet there is a syntax difference between into: and reduce: that...
New

Other popular topics Top

vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New

We're in Beta

About us Mission Statement