timbot
Partially applied functions and placeholder arguments
Hi there,
I am currently learning Elixir by going through the Mix and OTP guide on elixir-lang.org. I have read through the Getting Started guide already.
I am having trouble getting my head around the use of placeholder arguments when capturing and partially applying named functions. The specific examples that are confusing me are on this page here https://elixir-lang.org/getting-started/mix-otp/agent.html
def get(bucket, key) do
Agent.get(bucket, &Map.get(&1, key))
end
def put(bucket, key, value) do
Agent.update(bucket, &Map.put(&1, key, value))
end
If I understand correctly, the & in &Map.get and &Map.put is capturing the named functions so that they can be passed as arguments to the Agent.get and Agent.update functions. This makes sense to me. But the &1 is causing confusion.
I think the &1 is evaluating to bucket in each of these examples. I don’t see what else could be happening here. But if this is the case, then why can’t we just write bucket instead of &1? Wouldn’t that be a whole lot clearer?
I guess I could just carry on with the tutorial without properly understanding this point, but it seems like this is a crucial enough concept to ask an embarrassingly noob question on these forums.
Thanks in advance for helping me to understand this.
Marked As Solved
kokolegorille
It is the state of the Agent that get passed to the anonymous function.
Also Liked
benwilson512
There is nothing magic about how &1 is working here. Rather, it’s the Agent.get function that is doing the work. &Map.get(&1, key) is just an anonymous function that takes a map and grabs a key from it. For example:
iex(1)> key = :name
:name
iex(2)> fun = &Map.get(&1, key)
#Function<7.91303403/1 in :erl_eval.expr/5>
iex(3)> map = %{name: "Ben", country: "USA"}
%{country: "USA", name: "Ben"}
iex(4)> fun.(map)
"Ben"
In this example, &1 becomes whatever you pass to it, in my case map
When you do:
Agent.get(bucket, &Map.get(&1, key))
This is exactly equivalent to just doing:
fun = &Map.get(&1, key)
Agent.get(bucket, fun)
where fun in that example is 100% identical to the fun in my example.
SO how does it get the process state? Well, that’s the job of Agent.get. It takes that anonymous function sends it to the process, the process calls fun with its state, and sends the result back to you.
kokolegorille
Hello and welcome,
& is a shortcut for defining anonymous function, and &1, &2… are the parameters to this function.
&Map.get(&1, key)
# is equal to
fn x -> Map.get(x, key) end
You might find version with two parameters, in particular with reduce…
For example.
iex> Enum.reduce [1, 2, 3], & &1 + &2
6
# is equal to
iex> Enum.reduce [1, 2, 3], fn x, acc -> x + acc end
kokolegorille
That is the power of function as first class citizen, You can pass the implementation as an argument ![]()
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









