Hello, okay I checked.

Well, there was a discussion 7 years ago when Access.filter/1 was 
introduced but Access.find/1 was not.

Maybe opinions might have changed since then?

When going into the PR from back then I find the reasoning not very strong 
on not merging Access.find/1 because "it could be expressed by a more 
strictly defined Access.filter/1". 

I don't find that to be true. It has pretty much has the same use cases as 
Enum.find/2 when used with get_in/2, for example. 

Writing a very convoluted filter predicate to catch only the first 
occurrence when you really need to do that - we basically found that to be 
very unelegant. I really tried to cram our use case into the 
Access.filter/1 approach and it was not good.

An added benefit is that we do not walk the rest of the list - once an 
element is found, the tail is just appended in updates. It has therefore a 
slightly better performance for its specific use case over Access.filter/1. 
You also don't get a list you have to Access.all after. I mean, it's 
basically like Enum.find/2 instead of Enum.filter/2.

Btw, our use case was as follows:

We have a data structure representing a testcase to be run. Later on we 
want to verify some counter updates done in that TC. We reuse the data 
structure describing the TC. For this particular requirement regarding the 
counter updates only the first occurrence of a particular procedure will 
behave different. It has no other criteria it is different or can be told 
apart by, so we just update the first occurrence for this check with a flag 
for easier post-processing of the counter data. This flag has no relevance 
to other parts of our testing system, and if TC authors add it manually, 
they might forget. We simply use internally Access.find/1 to specifically 
pick that one.

When you have very clear, distinct criteria like in a DB row update (like 
there's only one "Jane Smith" with ID 42) then there would be no be 
advantage over Access.filter/1. So it's situational, but in the situations 
it's useful it's hard to express otherwise. For example once you 
Access.filter/1 you can no longer do something like Access.at/1 because it 
directly moves you into the elements.

Sorry for the long post, but I hope it conveys the rationale.

Best regards, 
Oliver




On Wednesday, March 20, 2024 at 10:07:33 AM UTC+1 an.le...@gmail.com wrote:

> Right now I’m a bit drowning in work but IIRC there already was a proposal 
> for this, has anyone searched the mailing list?
>
> On Wed, Mar 20, 2024, at 12:17 AM, Jean Klingler wrote:
>
> I like it. It would be to `Access.filter` what `Enum.find` is to 
> `Enum.filter`.
> I think it would be a nice addition as it can express operations that 
> would be quite verbose otherwise.
>
> Le mer. 20 mars 2024 à 02:30, 'oliver....@googlemail.com' via 
> elixir-lang-core <elixir-l...@googlegroups.com> a écrit :
>
> 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
>
>
> -- 
> 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-co...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/elixir-lang-core/44ed5beb-1730-46d7-931a-217825cc4432n%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/elixir-lang-core/44ed5beb-1730-46d7-931a-217825cc4432n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
>
> -- 
> 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-co...@googlegroups.com.
>
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/elixir-lang-core/CANnyoha%2BwMRpTy_H2%3Dwy8sWjSQgXPpY-cbaL65Tx7D_AK7o1GA%40mail.gmail.com
>  
> <https://groups.google.com/d/msgid/elixir-lang-core/CANnyoha%2BwMRpTy_H2%3Dwy8sWjSQgXPpY-cbaL65Tx7D_AK7o1GA%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
>
>

-- 
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/61e2ada8-1ba6-4945-9013-2cec1d1cf457n%40googlegroups.com.

Reply via email to