Reputation: 1079
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
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
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
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