From ff793acf03456b6bd4c12ea330a9311f7e94cc77 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Sun, 21 Dec 2014 04:37:54 -0500 Subject: [PATCH] Implement a tail-recursive list map. --- src/hope.app.src | 2 +- src/hope_list.erl | 47 ++++++++++++++++++++++++++++++++++++++++ test/hope_list_SUITE.erl | 9 ++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/hope.app.src b/src/hope.app.src index 64cce31..460fc9e 100644 --- a/src/hope.app.src +++ b/src/hope.app.src @@ -1,7 +1,7 @@ {application, hope, [ {description, "Higher Order Programming in Erlang"}, - {vsn, "1.6.0"}, + {vsn, "1.7.0"}, {registered, []}, {applications, [ kernel, diff --git a/src/hope_list.erl b/src/hope_list.erl index 0d71ece..91ab916 100644 --- a/src/hope_list.erl +++ b/src/hope_list.erl @@ -6,15 +6,62 @@ -export( [ unique_preserve_order/1 + , map/2 , map_rev/2 , map_slow/2 ]). +-define(RECURSION_LIMIT, 1000). + + -type t(A) :: [A]. +%% @doc Tail-recursive equivalent of lists:map/2 +%% @end +-spec map([A], fun((A) -> (B))) -> + [B]. +map(Xs, F) -> + map(Xs, F, 0). + +-spec map([A], fun((A) -> (B)), non_neg_integer()) -> + [B]. +map([], _, _) -> + []; +map([X1], F, _) -> + Y1 = F(X1), + [Y1]; +map([X1, X2], F, _) -> + Y1 = F(X1), + Y2 = F(X2), + [Y1, Y2]; +map([X1, X2, X3], F, _) -> + Y1 = F(X1), + Y2 = F(X2), + Y3 = F(X3), + [Y1, Y2, Y3]; +map([X1, X2, X3, X4], F, _) -> + Y1 = F(X1), + Y2 = F(X2), + Y3 = F(X3), + Y4 = F(X4), + [Y1, Y2, Y3, Y4]; +map([X1, X2, X3, X4, X5 | Xs], F, Count) -> + Y1 = F(X1), + Y2 = F(X2), + Y3 = F(X3), + Y4 = F(X4), + Y5 = F(X5), + Ys = + case Count > ?RECURSION_LIMIT + of true -> map_slow(Xs, F) + ; false -> map (Xs, F, Count + 1) + end, + [Y1, Y2, Y3, Y4, Y5 | Ys]. + + %% @doc lists:reverse(map_rev(L, F)) %% @end -spec map_slow([A], fun((A) -> (B))) -> diff --git a/test/hope_list_SUITE.erl b/test/hope_list_SUITE.erl index 38d406a..6967458 100644 --- a/test/hope_list_SUITE.erl +++ b/test/hope_list_SUITE.erl @@ -14,6 +14,7 @@ , t_hope_list_specs/1 , t_map_rev/1 , t_map_slow/1 + , t_map/1 ]). @@ -35,6 +36,7 @@ groups() -> , t_hope_list_specs , t_map_rev , t_map_slow + , t_map ], Properties = [parallel], [{?GROUP, Properties, Tests}]. @@ -54,6 +56,13 @@ t_map_slow(_Cfg) -> [2, 3, 4] = hope_list:map_slow([1, 2, 3], F), [] = hope_list:map_slow([], F). +t_map(_Cfg) -> + F = fun (N) -> N + 1 end, + Xs = lists:seq(1, 5010), + Ys = lists:map(F, Xs), + Ys = hope_list:map(Xs, F), + [] = hope_list:map([], F). + t_unique_preserve_order(_Cfg) -> ?PROPTEST(prop_unique_preserve_order). -- 2.20.1