Hi.
I already made a PR but was redirected here. ;-)
This new function Access.find/1 would basically work like Enum.find/2 but for get_in/2 and similar functions.
It can be used for scenarios like:
- Popping the first found element.
- Updating only the first found match in a list.
- To get_in/2 an element directly instead of piping from get_in/2 into Enum.find/2.
The implementation is very similar to Access.filter/1 and Access.at/1.
We added this functions as utility function in our own project because we couldn't really find an elegant way to do such pointed updates with the existing functions.
These are the examples I would have included in the doc string:
iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]
iex> get_in(list, [Access.find(&(&1.salary > 20)), :name])
"francine"
iex> get_and_update_in(list, [Access.find(&(&1.salary <= 40)), :name], fn prev ->
...> {prev, String.upcase(prev)}
...> end)
{"john", [%{name: "JOHN", salary: 10}, %{name: "francine", salary: 30}]}
iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]
iex> pop_in(list, [Access.find(&(&1.salary <= 40))])
{%{name: "john", salary: 10}, [%{name: "francine", salary: 30}]}
iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]
iex> get_in(list, [Access.find(&(&1.salary >= 50)), :name])
nil
iex> get_and_update_in(list, [Access.find(&(&1.salary >= 50)), :name], fn prev ->
...> {prev, String.upcase(prev)}
...> end)
{nil, [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]}
Thanks,
Oliver