Kernel.get_and_update_in

You're seeing just the function get_and_update_in, go back to Kernel module for more information.
Link to this function

get_and_update_in(data, keys, fun)

View Source

Specs

get_and_update_in(
  structure,
  keys,
  (term() | nil -> {current_value, new_value} | :pop)
) :: {current_value, new_structure :: structure}
when structure: Access.t(),
     keys: [any(), ...],
     current_value: Access.value(),
     new_value: Access.value()

Gets a value and updates a nested structure.

data is a nested structure (that is, a map, keyword list, or struct that implements the Access behaviour).

The fun argument receives the value of key (or nil if key is not present) and must return one of the following values:

  • a two-element tuple {current_value, new_value}. In this case, current_value is the retrieved value which can possibly be operated on before being returned. new_value is the new value to be stored under key.

  • :pop, which implies that the current value under key should be removed from the structure and returned.

This function uses the Access module to traverse the structures according to the given keys, unless the key is a function, which is detailed in a later section.

Examples

This function is useful when there is a need to retrieve the current value (or something calculated in function of the current value) and update it at the same time. For example, it could be used to read the current age of a user while increasing it by one in one pass:

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_and_update_in(users, ["john", :age], &{&1, &1 + 1})
{27, %{"john" => %{age: 28}, "meg" => %{age: 23}}}

Functions as keys

If a key is a function, the function will be invoked passing three arguments:

  • the operation (:get_and_update)
  • the data to be accessed
  • a function to be invoked next

This means get_and_update_in/3 can be extended to provide custom lookups. The downside is that functions cannot be stored as keys in the accessed data structures.

When one of the keys is a function, the function is invoked. In the example below, we use a function to get and increment all ages inside a list:

iex> users = [%{name: "john", age: 27}, %{name: "meg", age: 23}]
iex> all = fn :get_and_update, data, next ->
...>   data |> Enum.map(next) |> Enum.unzip()
...> end
iex> get_and_update_in(users, [all, :age], &{&1, &1 + 1})
{[27, 23], [%{name: "john", age: 28}, %{name: "meg", age: 24}]}

If the previous value before invoking the function is nil, the function will receive nil as a value and must handle it accordingly (be it by failing or providing a sane default).

The Access module ships with many convenience accessor functions, like the all anonymous function defined above. See Access.all/0, Access.key/2, and others as examples.