Re: Add lists:find/2,3
Steve Vinoski <[email protected]>
| Newsgroups | gmane.comp.lang.erlang.patches |
|---|---|
| Message-ID | <CAO+zUOUqCJUGebiXkGqupgjTj12EGqhKXy5hqdf+d7CqKMdM2A@mail.gmail.com> |
lists:member/2 matches (using =:=) entire elements to determine whether or not they are present in the list, whereas the proposed lists:find/2,3 allows the caller to pass a fun to test for element presence. The fun allows the caller to ignore fields of an element that's a tuple, record etc. for purposes of determining whether something is or is not present in the list. Therefore lists:member/2 can't do what the proposed lists:find/2,3 can do. --steve On Wed, Nov 13, 2013 at 9:08 AM, Serge Aleynikov <[email protected]>wrote: > Since finding an element in the list is already doable via lists:member/2, > it seems to me that there's very little benefit in that find/2 function. > Whereas a more valuable addition would be to find an index of the element > in the given list. An example of a common use case for that would be to > locate a field's position in a mnesia table by name (e.g. index_of): > > update_table(Table, FieldName, Value) -> > Attrs = mnesia:table_info(Table, attributes), > {ok, Pos} = index_of(FieldName, Attrs), > R = mnesia:dirty_read(Table, Key), > R1 = setelement(Pos, R, NewValue), > ok = mnesia:dirty_write(Table, R1). > > index_of(Value, List) -> > index_of(Value, List, 1). > index_of(V, [V|T], N) -> > {ok, N}; > index_of(V, [_|T], N) -> > index_of(V, T, N+1); > index_of(_, [], _) -> > false. > > > On Wed, Nov 13, 2013 at 5:48 AM, Thomas Järvstrand <[email protected]>wrote: > >> A more generic version would be to return the first result of applying >> the fun to an element that does not return false. That way you can choose >> whether to return the actual element, the result of the computation you >> just or even something completely different. The user is also free to wrap >> the result in case he/she is worried that the return value might be `false`. >> >> Example implementation: >> >> *find(_MatchF, []) ->* >> >> * false;* >> >> >> >> >> *find(MatchF, [X|Xs]) -> case MatchF(X) of false -> find(MatchF, >> Xs); Val -> Val end.* >> >> Thomas >> >> >> 2013/10/22 Anthony Ramine <[email protected]> >> >>> Forwarding to list. >>> >>> -- >>> Anthony Ramine >>> >>> Le 22 oct. 2013 à 11:56, Anthony Ramine <[email protected]> a écrit : >>> >>> > Maybe we could just have dropuntil(F, L) -> dropwhile(fun (X) -> not >>> F(X) end, L). >>> > >>> > Of course, the function would be written less naively to avoid >>> constructing a new fun. >>> > >>> > -- >>> > Anthony Ramine >>> > >>> > Le 14 oct. 2013 à 15:52, Sean Cribbs <[email protected]> a écrit : >>> > >>> >> #1: Would tagging the return value address like Masklinn mentions >>> address your concern? {ok, Term} | error (instead of a default value)? >>> >> >>> >> #2: Also, I considered dropwhile but it involves introducing another >>> fun, whereas the version I wrote is direct. >>> >> >>> >> >>> >> On Mon, Oct 14, 2013 at 5:28 AM, Anthony Ramine <[email protected]> >>> wrote: >>> >> Hello Sean, >>> >> >>> >> I don't like this patch. >>> >> >>> >> 1/ You can't know whether an element was found or not if the list >>> elements are arbitrary terms. >>> >> 2/ I don't see why you would say people hack either foreach/2 or >>> foldl/3 to do that when they should just use dropwhile/2. >>> >> >>> >> A naive implementation of find/2 using dropwhile/2: >>> >> >>> >> find(F, L) -> >>> >> case dropwhile(fun (E) -> not F(E) end, L) of >>> >> [] -> undefined; >>> >> [E|_] -> E >>> >> end. >>> >> >>> >> Regards, >>> >> >>> >> -- >>> >> Anthony Ramine >>> >> >>> >> Le 14 oct. 2013 à 02:44, Sean Cribbs <[email protected]> a écrit : >>> >> >>> >>> `lists:find/2,3` returns the first element of the passed list for >>> which the predicate fun returns `true`. If no elements result in the >>> predicate being true, `undefined` (/2) or the given default value (/3) is >>> returned. >>> >>> >>> >>> ## Why this new feature? >>> >>> >>> >>> A common task is to select the first element from a list that >>> matches a condition, but there is no existing lists function or language >>> feature that avoids traversing the entire list, while still returning a >>> "safe" value. `lists:find/2,3` codifies the pattern of a tail-recursive >>> search for the matching item without resorting to exceptions (used to abort >>> `foreach/2` or `foldl/3`) and always returns either the first matching >>> item, or an otherwise safe value. >>> >>> >>> >>> ## Risks / uncertain artifacts >>> >>> >>> >>> It is unclear the desired order of arguments for the 3-arity >>> version. I have made the default value the final argument which is >>> consistent with `application:get_env/3` and `proplists:get_value/3`, but >>> most functions in lists place the `List` argument last. >>> >>> >>> >>> ## How did you solve it? >>> >>> >>> >>> Following the patterns of other functions in the lists module, >>> `lists:find/3` tests the predicate function against the head of the list, >>> returning the head if the predicate passes, or recursing over the tail if >>> it does not. >>> >>> >>> >>> https://github.com/erlang/otp/pull/102 >>> >>> >>> >>> -- >>> >>> Sean Cribbs <[email protected]> >>> >>> Software Engineer >>> >>> Basho Technologies, Inc. >>> >>> http://basho.com/ >>> >>> _______________________________________________ >>> >>> erlang-patches mailing list >>> >>> [email protected] >>> >>> http://erlang.org/mailman/listinfo/erlang-patches >>> >> >>> >> >>> >> >>> >> >>> >> -- >>> >> Sean Cribbs <[email protected]> >>> >> Software Engineer >>> >> Basho Technologies, Inc. >>> >> http://basho.com/ >>> > >>> >>> _______________________________________________ >>> erlang-patches mailing list >>> [email protected] >>> http://erlang.org/mailman/listinfo/erlang-patches >>> >> >> >> _______________________________________________ >> erlang-patches mailing list >> [email protected] >> http://erlang.org/mailman/listinfo/erlang-patches >> >> > > _______________________________________________ > erlang-patches mailing list > [email protected] > http://erlang.org/mailman/listinfo/erlang-patches > > _______________________________________________ erlang-patches mailing list [email protected] http://erlang.org/mailman/listinfo/erlang-patches