I have a feeling there's probably a better way to do this, but I couldn't 
find it in the history.

This would let you do something like this:
iex> users = [%{name: "john", age: 27, employment: %{title: "Developer", 
salary: 100}}, %{name: "meg", age: 23, employment: %{title: "Manager", 
salary: 200}}]
iex> get_in(users, [Access.all(), Access.keys([:name, employment: 
[:title]])])
[%{employment: %{title: "Developer"}, name: "john"}, %{name: "meg", 
employment: %{title: "Manager"}}]

With keys partially implemented like this
def keys(keys) do
  fn
    :get, data, next ->
      next.(take(data, keys))

    :get_and_update, data, next ->
      values = take(data, keys)

      case next.(values) do
        {values, :pop} -> {values, Map.drop(data, keys)}
        {values, updates} -> {values, updates}
      end
  end
end

And then that `take` function something like this:
@doc """
## Examples
    iex> Access.take(%{name: "john", age: 52}, [:name, :age, :height])
    %{name: "john", age: 52}

    iex> Access.take(%{name: "john", age: 52, employment: %{title: 
"Developer", salary: 100}}, [:name, :height, employment: [:title]])
    %{name: "john", employment: %{title: "Developer"}}
"""
def take(container, keys) when is_list(keys) do
  cond do
    Enum.all?(keys, &is_atom/1) and is_map(container) ->
      Map.take(container, keys)

    is_map(container) ->
      keys
      |> Enum.group_by(&is_atom/1)
      |> Enum.reduce(%{}, fn
        {true, keys}, map ->
          Map.merge(map, Map.take(container, keys))

        {false, pairs}, map ->
          Map.merge(
            map,
            for({k, v} <- pairs, into: %{}, do: {k, take(Map.get(container, 
k), v)})
          )
      end)
  end
end

def take(_container, keys) when is_list(keys) do
  raise ArgumentError, "Access.take expects the keys to be a list of atoms 
or keyword list, got: " <> inspect(keys)
end

-- 
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 on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/30949654-b64a-4241-8416-60f2e0d462fen%40googlegroups.com.

Reply via email to