Skip to content

Commit a31dcbf

Browse files
committed
Add lists:last/1 and lists:mapfoldl/3
Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent 8b9419a commit a31dcbf

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ also non string parameters (e.g. `Enum.join([1, 2], ",")`
1818
- Add support to Elixir `Enumerable` protocol also for `Enum.all?`, `Enum.any?`, `Enum.each` and
1919
`Enum.filter`
2020
- Add support for `is_bitstring/1` construct which is used in Elixir protocols runtime.
21+
- Support for `lists:last/1` and `lists:mapfoldl/3`
2122

2223
### Changed
2324

libs/estdlib/src/lists.erl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
-export([
3333
map/2,
3434
nth/2,
35+
last/1,
3536
member/2,
3637
delete/2,
3738
reverse/1,
@@ -45,6 +46,7 @@
4546
keytake/3,
4647
foldl/3,
4748
foldr/3,
49+
mapfoldl/3,
4850
all/2,
4951
any/2,
5052
flatten/1,
@@ -90,6 +92,16 @@ nth(1, [H | _T]) ->
9092
nth(Index, [_H | T]) when Index > 1 ->
9193
nth(Index - 1, T).
9294

95+
%%-----------------------------------------------------------------------------
96+
%% @param L the proper list from which to get the last item
97+
%% @returns the last item of the list.
98+
%% @doc Get the last item of a list.
99+
%% @end
100+
%%-----------------------------------------------------------------------------
101+
-spec last(L :: nonempty_list(E)) -> E.
102+
last([E]) -> E;
103+
last([_H | T]) -> last(T).
104+
93105
%%-----------------------------------------------------------------------------
94106
%% @param E the member to search for
95107
%% @param L the list from which to get the value
@@ -372,6 +384,24 @@ foldl(Fun, Acc0, [H | T]) ->
372384
Acc1 = Fun(H, Acc0),
373385
foldl(Fun, Acc1, T).
374386

387+
%%-----------------------------------------------------------------------------
388+
%% @param Fun the function to apply
389+
%% @param Acc0 the initial accumulator
390+
%% @param List the list over which to fold
391+
%% @returns the result of mapping and folding Fun over L
392+
%% @doc Combine `map/2' and `foldl/3' in one pass.
393+
%% @end
394+
%%-----------------------------------------------------------------------------
395+
-spec mapfoldl(fun((A, Acc) -> {B, Acc}), Acc, [A]) -> {[B], Acc}.
396+
mapfoldl(Fun, Acc0, List1) ->
397+
mapfoldl0(Fun, {[], Acc0}, List1).
398+
399+
mapfoldl0(_Fun, {List1, Acc0}, []) ->
400+
{?MODULE:reverse(List1), Acc0};
401+
mapfoldl0(Fun, {List1, Acc0}, [H | T]) ->
402+
{B, Acc1} = Fun(H, Acc0),
403+
mapfoldl0(Fun, {[B | List1], Acc1}, T).
404+
375405
%%-----------------------------------------------------------------------------
376406
%% @equiv foldl(Fun, Acc0, reverse(List))
377407
%% @doc Fold over a list of terms, from right to left, applying Fun(E, Accum)

tests/libs/estdlib/test_lists.erl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ test() ->
4646
ok = test_split(),
4747
ok = test_usort(),
4848
ok = test_filtermap(),
49+
ok = test_last(),
50+
ok = test_mapfoldl(),
4951
ok.
5052

5153
test_nth() ->
@@ -296,4 +298,17 @@ test_filtermap() ->
296298
),
297299
ok.
298300

301+
test_last() ->
302+
?ASSERT_ERROR(lists:last([]), function_clause),
303+
?ASSERT_MATCH(a, lists:last([a])),
304+
?ASSERT_MATCH(b, lists:last([a, b])),
305+
?ASSERT_ERROR(lists:last([a | b]), function_clause),
306+
ok.
307+
308+
test_mapfoldl() ->
309+
?ASSERT_MATCH({[], 1}, lists:mapfoldl(fun(X, A) -> {X * A, A + 1} end, 1, [])),
310+
?ASSERT_MATCH({[1, 4, 9], 4}, lists:mapfoldl(fun(X, A) -> {X * A, A + 1} end, 1, [1, 2, 3])),
311+
?ASSERT_ERROR(lists:mapfoldl(fun(X, A) -> {X * A, A + 1} end, 1, foo), function_clause),
312+
ok.
313+
299314
id(X) -> X.

0 commit comments

Comments
 (0)