Most

Most

Why is the capture syntax &+/2 equivalent to &(&1 + &2)

I don’t understand how the capture syntax in the following expression is aware of how to use arguments without specifying &1 and &2:
Enum.reduce([1, 2, 3], 0, &+/2)

I understand this version of an equivalent expression since it is explicit how the arguments &1 and &2 are used in the function:
Enum.reduce([1, 2, 3], 0, &(&1 + &2))

Most Liked

peerreynders

peerreynders

It simply takes advantage of the positional function parameters.

+/2 is Kernel.+/2, i.e. Kernel.+(left, right) is equivalent to left + right.

The & operator captures the function rather than evaluate it - so it’s &Kernel.+/2 or &+/2.

Now look at the spec for Enum.reduce/3

reduce(t, any, (element, any -> any)) :: any

(element, any -> any) tells us that it takes a two parameter function. The first parameter (element) comes from the enumeration, the second parameter (any) is the accumulator which is the same type as the function’s result.

So the element (first) argument goes into the left parameter and the any (second) argument goes into right parameter of Kernel.+/2 (… and the result becomes the next right and so on).

bbense

bbense

Let’s start with some iex

iex(1)> h Kernel.+/1
def +(value)
Arithmetic unary plus.
Allowed in guard tests. Inlined by the compiler.
Examples
┃ iex> +1
┃ 1
iex(2)> h Kernel.+/2
def +(left, right)
Arithmetic addition.
Allowed in guard tests. Inlined by the compiler.
Examples
┃ iex> 1 + 2
┃ 3

The important thing to remember with Elixir is that no matter what the syntax looks like, it all gets turned into function calls. Every time you use + it gets turned into one of those two functions.

iex(3)> quote do: 1 + 2
{:+, [context: Elixir, import: Kernel], [1, 2]}
iex(4)> quote do: + 1
{:+, [context: Elixir, import: Kernel], [1]}

So let’s look at what the parser sees in each case.

iex> +(1, 2)

In this case the parser looks to somehow call Kernel.+1/ but it’s given an arg list that
is two elements long. This generates an syntax error.

iex> 1 Kernel.+ 2

Here the parser sees a number so it starts looking for an infix operator it can turn into a function call. While + is defined as an infix operator, arbitrary elixir functions cannot be used
as infix operators. So again it generates a syntax error.

What is going on is that the parser is attempting to be as friendly as possible and allow you to use constructs you are familiar with like 1 + 2. However, that can only be extended so far before it starts to break the underlying model of a functional programming language. + is particularly tricky since it exists in the parser as both a prefix and infix operator.

The effects you see are the attempts of the parser to understand + as both. Once you
put Kernel.+ into the equation all the special parsing rules are turned off, and it behaves like any other Elixir function.

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
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
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New

Other popular topics Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement