cogle
cogle

Reputation: 1079

How does the '&' operator work?

I am having trouble understand the '&' operator in the following context.

  @doc "Marks a task as executed"
  def put_task(task, project) do
    item = {task, project}
    Agent.update(__MODULE__, &MapSet.put(&1, item))
  end

It seems that in this case the '&1' is referring to the map object itself, but I am curious as to how this works. Is it passing itself in as an argument I looked into this in the docs but couldn't find out if this was exactly what was going on. I would be grateful if somebody could help me understand what is exactly going on and what &1 refers to and if it refers to the MapSet how is this possible.

Upvotes: 9

Views: 2251

Answers (3)

Paweł Obrok
Paweł Obrok

Reputation: 23164

The &1 is the first argument of the function. The whole & notation is basically an alternative way to express anonymous functions - there's nothing specific to Enum or Agent about it. Let's take this example:

fn (x, y, z) -> (x + z) * y end

This is an anonymous function that takes 3 arguments, adds the first and third one and multiplies the result by the second one. With the & notation:

&((&1 + &3) * &2)

Think of the &1, &2 and &3 as placeholders in an expression where the arguments will go. So when you do

Agent.update(__MODULE__, &MapSet.put(&1, item))

You're calling Agent.update with a one-argument function that calls MapSet.put with that argument and item - whatever that is. It's equivalent to:

Agent.update(__MODULE__, fn x -> MapSet.put(x, item) end)

Upvotes: 25

coderVishal
coderVishal

Reputation: 9099

Lets consider a more simple example,

Enum.map [1, 2, 3, 4], &(&1 * 2)

Enum.map [1, 2, 3, 5], fn x -> x * 2 end // Exactly like above

To Enum.map we are basically passing a list and an anonymous function. Enum.map expects the anonymous function to have atleast one argument(no brainer, it passes each element of the list to anonymous function). So here &1 which is the first argument of the anonymous function which will be set by Enum.map when it calls our anonymous function. Enum.map loops through the list calling our anonymous function each time with a different element of our list.

Though I do not know the implementation of the Agent.update, but as far as I see what its doing is, Agent.update is calling on the agent which is _MODULE_ and on this applying function Map.Set which receives the old state of the agent, and sets new state of the agent. In other words you could say &1 is the old state of the agent

Upvotes: 5

Dogbert
Dogbert

Reputation: 222188

I would be grateful if somebody could help me understand what is exactly going on and what &1 refers to and if it refers to the MapSet how is this possible.

Agent.update/3 calls the given function with the current state, and stores the returned value as the new state. Since &MapSet.put(&1, item) is the same as fn x -> MapSet.put(x, item) end, x here becomes the old state, and the new MapSet returned by MapSet.put/2 becomes the new state of the agent.

For this code to function, there must be a call to Agent.start or Agent.start_link with name: __MODULE__ and a function that returns {:ok, map_set} where map_set is any MapSet somewhere in the code.

Upvotes: 4

Related Questions