Exadra37
Agent.get_and_update/2 docs example doesn't return what I expect
After some months out of Elixir I am trying to refresh my knowledge on it, therefore I am going through the Elixir for Programmers 2 from @pragdave, because I have done the first edition and it was the one that made made my brain click in the functional programming paradigm.
So I am now at the Agent lesson and he shows the same example we can see in the docs:
iex(12)> Agent.get_and_update(counter, fn state -> {state, state + 1} end)
2
iex(13)> Agent.get(counter, fn state -> state end)
3
So, from the function name I would expect to have back the new state, but instead I got back the old state. I know I can control that from the anonymous function I pass, but my question is why the example in the docs is done this way and not this way:
Agent.get_and_update(counter, fn state -> state = state + 1; {state, state} end)
4
iex(15)> Agent.get_and_update(counter, fn state -> state = state + 1; {state, state} end)
5
iex(16)> Agent.get_and_update(counter, fn state -> state = state + 1; {state, state} end)
I am not seeing immediately how useful it can be to update a state in the Agent and get back the old state, instead of the new state, but for sure it will exist some use cases for it.
Wouldn’t be better to have the official docs showing an example that returns the updated state?
Most Liked
l00ker
I think what may not be clear at first is that get_and_update/3 gives you control over what is returned vs what is state. The control over what is returned is what is useful in real world projects.
iex(1)> {:ok, pid} = Agent.start_link(fn -> 42 end)
{:ok, #PID<0.113.0>}
iex(2)> Agent.get_and_update(pid, fn state -> {:ok, state + 1} end)
:ok
iex(3)> Agent.get(pid, fn state -> state end)
43
iex(4)> Agent.get_and_update(pid, fn state -> {"ok", state + 1} end)
"ok"
iex(5)> Agent.get(pid, fn state -> state end)
44
iex(6)> Agent.get_and_update(pid, fn state -> {{:ok, state + 1}, state + 1} end)
{:ok, 45}
iex(7)> Agent.get(pid, fn state -> state end)
45
It keeps the state – in this case, only an integer – completely separate from what is returned (think pattern matching). It’s even useful with get/3.
iex(8)> Agent.get(pid, fn state -> {:ok, state} end)
{:ok, 45}
iex(9)> Agent.get(pid, fn state -> state end)
45
iex(10)> Agent.get(pid, fn state -> %{my_value: state} end)
%{my_value: 45}
kokolegorille
I guess it would be called update_and_get ?! ![]()







