Current section
Files
Jump to
Current section
Files
src/stream.erl
-module(stream).
-compile([no_auto_import, nowarn_unused_vars]).
-export([new/0, next_with_timeout/2, next/1, write/2, from_list/1, close/1, to_iterator/1, collect/1, with/2, foreach/2, foreach_unless_error/2, map/2, filter/2, reduce/3]).
-export_type([pipe_message/1, stream/1]).
-opaque pipe_message(GVH) :: {another, GVH} | done.
-type stream(GVI) :: {stream, gleam@erlang@process:subject(pipe_message(GVI))}.
-spec new() -> stream(any()).
new() ->
{stream, gleam@erlang@process:new_subject()}.
-spec next_with_timeout(stream(GVS), integer()) -> {ok, GVS} | {error, nil}.
next_with_timeout(S, Timeout) ->
{stream, Subject} = S,
case gleam@erlang@process:'receive'(Subject, Timeout) of
{ok, {another, A}} ->
{ok, A};
{ok, done} ->
{error, nil};
{error, nil} ->
{error, nil}
end.
-spec next(stream(GVO)) -> {ok, GVO} | {error, nil}.
next(S) ->
next_with_timeout(S, (15 * 60) * 1000).
-spec write(stream(GVW), GVW) -> nil.
write(S, Value) ->
{stream, Subject} = S,
gleam@erlang@process:send(Subject, {another, Value}).
-spec from_list(list(GVL)) -> stream(GVL).
from_list(L) ->
S = new(),
gleam@otp@task:async(
fun() -> gleam@list:map(L, fun(A) -> write(S, A) end) end
),
S.
-spec close(stream(any())) -> nil.
close(S) ->
{stream, Subject} = S,
gleam@erlang@process:send(Subject, done).
-spec to_iterator(stream(GWA)) -> gleam@iterator:iterator(GWA).
to_iterator(S) ->
gleam@iterator:unfold(nil, fun(_) -> case next(S) of
{ok, A} ->
{next, A, nil};
{error, nil} ->
done
end end).
-spec collect(stream(GWD)) -> list(GWD).
collect(S) ->
_pipe = to_iterator(S),
gleam@iterator:to_list(_pipe).
-spec with(stream(any()), fun(() -> GWI)) -> GWI.
with(Stream, F) ->
Out = F(),
close(Stream),
Out.
-spec foreach(stream(GWJ), fun((GWJ) -> nil)) -> nil.
foreach(Stream, F) ->
case next(Stream) of
{ok, A} ->
F(A),
foreach(Stream, F);
{error, nil} ->
nil
end.
-spec foreach_unless_error(stream(GWL), fun((GWL) -> {ok, nil} | {error, GWN})) -> {ok,
nil} |
{error, GWN}.
foreach_unless_error(Stream, F) ->
case next(Stream) of
{ok, A} ->
case F(A) of
{ok, nil} ->
foreach_unless_error(Stream, F);
{error, Err} ->
{error, Err}
end;
{error, nil} ->
{ok, nil}
end.
-spec map(stream(GWS), fun((GWS) -> GWU)) -> stream(GWU).
map(Input, F) ->
Output = new(),
gleam@otp@task:async(
fun() ->
with(
Output,
fun() ->
foreach(
Input,
fun(A) ->
write(Output, F(A)),
nil
end
)
end
)
end
),
Output.
-spec filter(stream(GWW), fun((GWW) -> boolean())) -> stream(GWW).
filter(Input, P) ->
Output = new(),
gleam@otp@task:async(
fun() -> with(Output, fun() -> foreach(Input, fun(A) -> case P(A) of
true ->
write(Output, A);
false ->
nil
end end) end) end
),
Output.
-spec reduce(stream(GWZ), GXB, fun((GWZ, GXB) -> GXB)) -> GXB.
reduce(Input, Start, F) ->
case next(Input) of
{ok, A} ->
reduce(Input, F(A, Start), F);
{error, nil} ->
Start
end.