Can you please provide a link to the previous discussions? I recall dealing with some complexities around finding and not finding elements as well. Thanks!
On Wed, Mar 20, 2024 at 11:37 AM 'oliver....@googlemail.com' via elixir-lang-core <elixir-lang-core@googlegroups.com> wrote: > 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 > <https://groups.google.com/d/msgid/elixir-lang-core/61e2ada8-1ba6-4945-9013-2cec1d1cf457n%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-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4JBTYNG%2BFuuYu08uOYWNahxa6rbO8sWsvF%2B3O6nh7kXuA%40mail.gmail.com.