[erlang-patches] Add lists:find/2,3

Steve Vinoski <>
Wed Nov 13 15:23:29 CET 2013


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 <>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 <>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 <>
>>
>>> Forwarding to list.
>>>
>>> --
>>> Anthony Ramine
>>>
>>> Le 22 oct. 2013 à 11:56, Anthony Ramine <> 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 <> 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 <>
>>> 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 <> 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 <>
>>> >>> Software Engineer
>>> >>> Basho Technologies, Inc.
>>> >>> http://basho.com/
>>> >>> _______________________________________________
>>> >>> erlang-patches mailing list
>>> >>> 
>>> >>> http://erlang.org/mailman/listinfo/erlang-patches
>>> >>
>>> >>
>>> >>
>>> >>
>>> >> --
>>> >> Sean Cribbs <>
>>> >> Software Engineer
>>> >> Basho Technologies, Inc.
>>> >> http://basho.com/
>>> >
>>>
>>> _______________________________________________
>>> erlang-patches mailing list
>>> 
>>> http://erlang.org/mailman/listinfo/erlang-patches
>>>
>>
>>
>> _______________________________________________
>> erlang-patches mailing list
>> 
>> http://erlang.org/mailman/listinfo/erlang-patches
>>
>>
>
> _______________________________________________
> erlang-patches mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-patches
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-patches/attachments/20131113/b24cfd3f/attachment.html>


More information about the erlang-patches mailing list