Skip to content

Commit

Permalink
Add lists:last/1 and lists:mapfoldl/3
Browse files Browse the repository at this point in the history
Signed-off-by: Paul Guyot <[email protected]>
  • Loading branch information
pguyot committed Sep 22, 2024
1 parent 5b6d8af commit 7b622bb
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
30 changes: 30 additions & 0 deletions libs/estdlib/src/lists.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
-export([
map/2,
nth/2,
last/1,
member/2,
delete/2,
reverse/1,
Expand All @@ -45,6 +46,7 @@
keytake/3,
foldl/3,
foldr/3,
mapfoldl/3,
all/2,
any/2,
flatten/1,
Expand Down Expand Up @@ -90,6 +92,16 @@ nth(1, [H | _T]) ->
nth(Index, [_H | T]) when Index > 1 ->
nth(Index - 1, T).

%%-----------------------------------------------------------------------------
%% @param L the proper list from which to get the last item
%% @returns the last item of the list.
%% @doc Get the last item of a list.
%% @end
%%-----------------------------------------------------------------------------
-spec last(L :: nonempty_list(E)) -> E.
last([E]) -> E;
last([_H | T]) -> last(T).

%%-----------------------------------------------------------------------------
%% @param E the member to search for
%% @param L the list from which to get the value
Expand Down Expand Up @@ -372,6 +384,24 @@ foldl(Fun, Acc0, [H | T]) ->
Acc1 = Fun(H, Acc0),
foldl(Fun, Acc1, T).

%%-----------------------------------------------------------------------------
%% @param Fun the function to apply
%% @param Acc0 the initial accumulator
%% @param List the list over which to fold
%% @returns the result of mapping and folding Fun over L
%% @doc Combine `map/2` and `foldl/3` in one pass.
%% @end
%%-----------------------------------------------------------------------------
-spec mapfoldl(fun((A, Acc) -> {B, Acc}), Acc, [A]) -> {[B], Acc}.
mapfoldl(Fun, Acc0, List1) ->
mapfoldl0(Fun, {[], Acc0}, List1).

mapfoldl0(_Fun, {List1, Acc0}, []) ->
{?MODULE:reverse(List1), Acc0};
mapfoldl0(Fun, {List1, Acc0}, [H | T]) ->
{B, Acc1} = Fun(H, Acc0),
mapfoldl0(Fun, {[B | List1], Acc1}, T).

%%-----------------------------------------------------------------------------
%% @equiv foldl(Fun, Acc0, reverse(List))
%% @doc Fold over a list of terms, from right to left, applying Fun(E, Accum)
Expand Down
15 changes: 15 additions & 0 deletions tests/libs/estdlib/test_lists.erl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ test() ->
ok = test_split(),
ok = test_usort(),
ok = test_filtermap(),
ok = test_last(),
ok = test_mapfoldl(),
ok.

test_nth() ->
Expand Down Expand Up @@ -296,4 +298,17 @@ test_filtermap() ->
),
ok.

test_last() ->
?ASSERT_ERROR(lists:last([]), function_clause),
?ASSERT_MATCH(a, lists:last([a])),
?ASSERT_MATCH(b, lists:last([a, b])),
?ASSERT_ERROR(lists:last([a | b]), function_clause),
ok.

test_mapfoldl() ->
?ASSERT_MATCH({[], 1}, lists:mapfoldl(fun(X, A) -> {X * A, A + 1} end, 1, [])),
?ASSERT_MATCH({[1, 4, 9], 4}, lists:mapfoldl(fun(X, A) -> {X * A, A + 1} end, 1, [1, 2, 3])),
?ASSERT_ERROR(lists:mapfoldl(fun(X, A) -> {X * A, A + 1} end, 1, foo), function_clause),
ok.

id(X) -> X.

0 comments on commit 7b622bb

Please sign in to comment.