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

Serge Aleynikov <>
Wed Nov 13 15:08:52 CET 2013


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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-patches/attachments/20131113/c56a39a0/attachment-0001.html>


More information about the erlang-patches mailing list