Skip to content

Commit 1e3f501

Browse files
committed
Merge pull request #2350 from pguyot/w27/estdlib-lists-mapfoldr
estdlib: add lists:mapfoldr/3 These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents a0f647e + 264c911 commit 1e3f501

3 files changed

Lines changed: 29 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3333
- Added a Linux `gpio` driver for the generic_unix port (in `avm_unix`) using sysfs
3434
- Added `console:print_err/1` to write to standard error
3535
- Added `erlang:term_to_binary/2`, `erlang:is_builtin/3` and `erlang:bitstring_to_list/1`
36+
- Added `lists:mapfoldr/3`
3637

3738
### Changed
3839
- Updated network type db() to dbm() to reflect the actual representation of the type

libs/estdlib/src/lists.erl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
foldl/3,
5151
foldr/3,
5252
mapfoldl/3,
53+
mapfoldr/3,
5354
all/2,
5455
any/2,
5556
flatten/1,
@@ -412,6 +413,22 @@ mapfoldl0(Fun, {List1, Acc0}, [H | T]) ->
412413
{B, Acc1} = Fun(H, Acc0),
413414
mapfoldl0(Fun, {[B | List1], Acc1}, T).
414415

416+
%%-----------------------------------------------------------------------------
417+
%% @param Fun the function to apply
418+
%% @param Acc0 the initial accumulator
419+
%% @param List the list over which to fold
420+
%% @returns the result of mapping and folding Fun over List, from right to left
421+
%% @doc Combine `map/2' and `foldr/3' in one pass.
422+
%% @end
423+
%%-----------------------------------------------------------------------------
424+
-spec mapfoldr(fun((A, Acc) -> {B, Acc}), Acc, [A]) -> {[B], Acc}.
425+
mapfoldr(_Fun, Acc0, []) ->
426+
{[], Acc0};
427+
mapfoldr(Fun, Acc0, [H | T]) ->
428+
{Bs, Acc1} = mapfoldr(Fun, Acc0, T),
429+
{B, Acc2} = Fun(H, Acc1),
430+
{[B | Bs], Acc2}.
431+
415432
%%-----------------------------------------------------------------------------
416433
%% @equiv foldl(Fun, Acc0, reverse(List))
417434
%% @doc Fold over a list of terms, from right to left, applying Fun(E, Accum)

tests/libs/estdlib/test_lists.erl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,17 @@ test_mapfoldl() ->
477477
lists:mapfoldl(fun(X, A) -> {X * A, A + 1} end, 1, [1, 2, 3])
478478
),
479479
?ASSERT_ERROR(lists:mapfoldl(fun(X, A) -> {X * A, A + 1} end, 1, foo), function_clause),
480+
ok = test_mapfoldr(),
481+
ok.
482+
483+
test_mapfoldr() ->
484+
?ASSERT_MATCH({[], 1}, lists:mapfoldr(fun(X, A) -> {X * A, A + 1} end, 1, [])),
485+
%% Right-to-left: the accumulator visits 3, then 2, then 1.
486+
?ASSERT_MATCH(
487+
{[3, 4, 3], 4},
488+
lists:mapfoldr(fun(X, A) -> {X * A, A + 1} end, 1, [1, 2, 3])
489+
),
490+
?ASSERT_ERROR(lists:mapfoldr(fun(X, A) -> {X * A, A + 1} end, 1, foo), function_clause),
480491
ok.
481492

482493
test_append() ->

0 commit comments

Comments
 (0)