Skip to content

Commit de7a447

Browse files
authored
chore: Added s2_par:filtermap/2,3 functions (#39)
1 parent 86c3a18 commit de7a447

1 file changed

Lines changed: 34 additions & 2 deletions

File tree

src/s2_par.erl

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
%%%_* Exports ==========================================================
1010
-export([ map/2
1111
, map/3
12+
, filtermap/2
13+
, filtermap/3
1214
]).
1315

1416
-export_type([ opt/0
@@ -34,6 +36,15 @@ map(F, Xs) ->
3436
map(_F, [], _Opts) ->
3537
{ok, []};
3638
map(F, Xs, Opts) ->
39+
filtermap(fun(A) -> {true, F(A)} end, Xs, Opts).
40+
41+
-spec filtermap(fun((A) -> boolean() | {true, B}), [A]) -> maybe([maybe(B, _) | B], _).
42+
filtermap(F, Xs) ->
43+
filtermap(F, Xs, []).
44+
45+
filtermap(_F, [], _Opts) ->
46+
{ok, []};
47+
filtermap(F, Xs, Opts) ->
3748
Timeout = s2_lists:assoc(Opts, timeout, infinity),
3849
Errors = s2_lists:assoc(Opts, errors, false),
3950
Workers = s2_lists:assoc(Opts, workers, 0),
@@ -106,7 +117,15 @@ spawn_workers(F, Xs, Workers, ChunkSize) ->
106117
[proc_lib:spawn_link(?thunk(worker(F, C, Self))) || C <- Chunks].
107118

108119
worker(F, Chunk, Parent) ->
109-
s2_procs:send(Parent, [?lift(F(X)) || X <- Chunk]).
120+
s2_procs:send(Parent, worker_filtermap(F, Chunk)).
121+
122+
worker_filtermap(F, [X | Chunk]) ->
123+
case F(X) of
124+
true -> [?lift(X) | worker_filtermap(F, Chunk)];
125+
{true, Value} -> [?lift(Value) | worker_filtermap(F, Chunk)];
126+
false -> worker_filtermap(F, Chunk)
127+
end;
128+
worker_filtermap(_F, []) -> [].
110129

111130
%%%_ * Chunking --------------------------------------------------------
112131
chunk(Xs, Workers, ChunkSize)
@@ -136,14 +155,27 @@ divide(N, M) when N rem M =/= 0 -> N div M + 1.
136155
%%%_* Tests ============================================================
137156
-ifdef(TEST).
138157

139-
basic_test() ->
158+
map_basic_test() ->
140159
{ok, []} = map(fun(X) -> X + 1 end, []),
141160
{ok, Ys} = map(fun(X) -> X + 1 end, [0, 1, 2]),
142161
true = length(Ys) =:= 3,
143162
true = lists:member(1, Ys),
144163
true = lists:member(2, Ys),
145164
true = lists:member(3, Ys).
146165

166+
filtermap_basic_test() ->
167+
Fun = fun
168+
(X) when X rem 2 =:= 1 -> {true, X + 1};
169+
(_X) -> false
170+
end,
171+
172+
{ok, []} = filtermap(Fun, []),
173+
{ok, Ys} = filtermap(Fun, [0, 1, 2]),
174+
true = length(Ys) =:= 1,
175+
false = lists:member(1, Ys),
176+
true = lists:member(2, Ys),
177+
false = lists:member(3, Ys).
178+
147179
timeout_test() ->
148180
{ok, []} = map(fun(X) -> X + 1 end, [], [{timeout, 0}]),
149181
{error, timeout} = map(fun(X) -> X + 1 end, [0, 1, 2], [{timeout, 0}]).

0 commit comments

Comments
 (0)