, map_slow/2
, map_result/2 % Not tail-recursive
, first_match/2
+ , divide/2
]).
-
-define(DEFAULT_RECURSION_LIMIT, 1000).
-
-type t(A) ::
[A].
-
%% @doc Tail-recursive equivalent of lists:map/2
%% @end
-spec map([A], fun((A) -> (B))) ->
map_slow(Xs, F) ->
lists:reverse(map_rev(Xs, F)).
-
%% @doc Tail-recursive alternative to lists:map/2, which accumulates and
%% returns list in reverse order.
%% @end
of true -> {some, Tag}
; false -> first_match(Tests, X)
end.
+
+%% @doc Divide list into sublists of up to a requested size + a remainder.
+%% Order unspecified. Size < 1 raises an error:
+%% `hope_list__divide__size_must_be_a_positive_integer'
+%% @end
+-spec divide([A], pos_integer()) ->
+ [[A]].
+divide(_, Size) when Size < 1 orelse not is_integer(Size) ->
+ % Q: Why?
+ % A: For N < 0, what does it mean to have a negative-sized chunk?
+ % For N = 0, we can imagine that a single chunk is an empty list, but,
+ % how many such chunks should we produce?
+ % This is pretty-much equivalnet to the problem of deviding something by 0.
+ error(hope_list__divide__size_must_be_a_positive_integer);
+divide([], _) ->
+ [];
+divide([X1 | Xs], MaxChunkSize) ->
+ MoveIntoChunks =
+ fun (X2, {Chunk, Chunks, ChunkSize}) when ChunkSize >= MaxChunkSize ->
+ {[X2], [Chunk | Chunks], 1}
+ ; (X2, {Chunk, Chunks, ChunkSize}) ->
+ {[X2 | Chunk], Chunks, ChunkSize + 1}
+ end,
+ {Chunk, Chunks, _} = lists:foldl(MoveIntoChunks, {[X1], [], 1}, Xs),
+ [Chunk | Chunks].
, t_manual_map_result/1
, t_manual_map_rev/1
, t_manual_map_slow/1
+ , t_manual_divide/1
]).
, t_manual_map_result
, t_manual_map_rev
, t_manual_map_slow
+ , t_manual_divide
],
Properties = [parallel],
[{?GROUP, Properties, Tests}].
[2, 3, 4] = hope_list:map_slow([1, 2, 3], F),
[] = hope_list:map_slow([], F).
+t_manual_divide(_Cfg) ->
+ try
+ hope_list:divide([a, b, c], -1)
+ catch
+ error:hope_list__divide__size_must_be_a_positive_integer -> ok
+ end,
+ try
+ hope_list:divide([a, b, c], 0)
+ catch
+ error:hope_list__divide__size_must_be_a_positive_integer -> ok
+ end,
+ [[c], [b], [a]] = hope_list:divide([a, b, c], 1),
+ [[c], [b, a]] = hope_list:divide([a, b, c], 2),
+ [[c, b, a]] = hope_list:divide([a, b, c], 3),
+ [[c, b, a]] = hope_list:divide([a, b, c], 4),
+ [[c, b, a]] = hope_list:divide([a, b, c], 5),
+ try
+ hope_list:divide([], 0)
+ catch
+ error:hope_list__divide__size_must_be_a_positive_integer -> ok
+ end,
+ try
+ hope_list:divide([], -1)
+ catch
+ error:hope_list__divide__size_must_be_a_positive_integer -> ok
+ end,
+ [[f, e], [d, c], [b, a]] = hope_list:divide([a, b, c, d, e, f], 2),
+ [[f, e, d], [c, b, a]] = hope_list:divide([a, b, c, d, e, f], 3).
+
%% =============================================================================
%% Generated test cases
%% =============================================================================