Hi!

I've recently discovered that get_and_update_in/3 and friends can access 
multiple items at once via Access.all/0, Access.filter/1, and similar. It's 
a game changer for accessing deeply nested structures.

However, there is no function in the standard library for accessing 
multiple items of a map (similarly to items of a list). For maps where keys 
are something item IDs and not predefined atoms, I think such accessors 
would be very useful. In our codebase, for example, we often manipulate 
deeply nested structures that include such maps and want to access all 
values in such maps (e.g., when migrating data).

It's easy to write an accessor that accesses all values in a map (and 
similarly for keys or both keys and values):

@doc """
Returns a function that accesses all values in a map.

The returned function is typically passed as an accessor to 
`Kernel.get_in/2`,
`Kernel.get_and_update_in/3`, and friends.

## Examples

    iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
    iex> get_in(users, [AccessUtils.values(), :age])
    [27, 23]
    iex> update_in(users, [AccessUtils.values(), :age], fn age -> age + 1 
end)
    %{"john" => %{age: 28}, "meg" => %{age: 24}}
    iex> put_in(users, [AccessUtils.values(), :phone], nil)
    %{"john" => %{age: 27, phone: nil}, "meg" => %{age: 23, phone: nil}}

"""
@spec values() :: Access.access_fun(data :: map(), current_value :: list())
def values do
  fn
    :get, %{} = data, next ->
      Enum.map(data, fn {_key, value} -> next.(value) end)

    :get_and_update, %{} = data, next ->
      {reverse_gets, updated_data} =
        Enum.reduce(data, {[], %{}}, fn {key, value}, {gets, data_acc} ->
          case next.(value) do
            {get, update} -> {[get | gets], Map.put(data_acc, key, update)}
            :pop -> {[value | gets], data_acc}
          end
        end)

      {Enum.reverse(reverse_gets), updated_data}
  end
end

Nevertheless, I think it might be useful to include it in the Access module 
of the standard library. What do you think?

Note that something similar has already been discussed on Elixir Forum 
<https://elixirforum.com/t/how-to-use-update-in-on-multiple-map-keys-at-once-re-access-all/63963>
.

Best regards,
David

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/elixir-lang-core/847b6461-aaf4-4d2c-abbd-6b2ddee73b21n%40googlegroups.com.

Reply via email to