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

siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30877 112
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43622 214
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
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
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New

We're in Beta

About us Mission Statement