Current section

Files

Jump to
gleam_stdlib gen src gleam@iterator.erl
Raw

gen/src/gleam@iterator.erl

-module(gleam@iterator).
-compile(no_auto_import).
-export([unfold/2, repeatedly/1, repeat/1, from_list/1, fold/3, run/1, to_list/1, step/1, take/2, drop/2, map/2, append/2, flatten/1, flat_map/2, filter/2, cycle/1, range/2, find/2]).
-export_type([action/1, iterator/1, step/2]).
-type action(ATI) :: stop | {continue, ATI, fun(() -> action(ATI))}.
-opaque iterator(ATJ) :: {iterator, fun(() -> action(ATJ))}.
-type step(ATK, ATL) :: {next, ATK, ATL} | done.
-spec do_unfold(ATO, fun((ATO) -> step(ATP, ATO))) -> fun(() -> action(ATP)).
do_unfold(Initial, F) ->
fun() -> case F(Initial) of
{next, X, Acc} ->
{continue, X, do_unfold(Acc, F)};
done ->
stop
end end.
-spec unfold(ATT, fun((ATT) -> step(ATU, ATT))) -> iterator(ATU).
unfold(Initial, F) ->
{iterator, do_unfold(Initial, F)}.
-spec repeatedly(fun(() -> ATY)) -> iterator(ATY).
repeatedly(F) ->
unfold(nil, fun(_) -> {next, F(), nil} end).
-spec repeat(AUA) -> iterator(AUA).
repeat(X) ->
repeatedly(fun() -> X end).
-spec from_list(list(AUC)) -> iterator(AUC).
from_list(List) ->
Yield = fun(Acc) -> case Acc of
[] ->
done;
[Head | Tail] ->
{next, Head, Tail}
end end,
unfold(List, Yield).
-spec do_fold(fun(() -> action(AUF)), AUH, fun((AUF, AUH) -> AUH)) -> AUH.
do_fold(Continuation, Initial, F) ->
case Continuation() of
{continue, Element, Iterator} ->
do_fold(Iterator, F(Element, Initial), F);
stop ->
Initial
end.
-spec fold(iterator(AUI), AUK, fun((AUI, AUK) -> AUK)) -> AUK.
fold(Iterator, Initial, F) ->
do_fold(erlang:element(2, Iterator), Initial, F).
-spec run(iterator(any())) -> nil.
run(Iterator) ->
fold(Iterator, nil, fun(_, _) -> nil end).
-spec to_list(iterator(AUN)) -> list(AUN).
to_list(Iterator) ->
gleam@list:reverse(fold(Iterator, [], fun(E, Acc) -> [E | Acc] end)).
-spec step(iterator(AUQ)) -> step(AUQ, iterator(AUQ)).
step(Iterator) ->
case (erlang:element(2, Iterator))() of
stop ->
done;
{continue, E, A} ->
{next, E, {iterator, A}}
end.
-spec do_take(fun(() -> action(AUV)), integer(), list(AUV)) -> list(AUV).
do_take(Continuation, Desired, Acc) ->
case Desired > 0 of
true ->
case Continuation() of
{continue, Element, Iterator} ->
do_take(Iterator, Desired - 1, [Element | Acc]);
stop ->
gleam@list:reverse(Acc)
end;
false ->
gleam@list:reverse(Acc)
end.
-spec take(iterator(AUZ), integer()) -> list(AUZ).
take(Iterator, Desired) ->
do_take(erlang:element(2, Iterator), Desired, []).
-spec do_drop(fun(() -> action(AVC)), integer()) -> fun(() -> action(AVC)).
do_drop(Continuation, Desired) ->
case Desired > 0 of
true ->
case Continuation() of
{continue, _, Iterator} ->
do_drop(Iterator, Desired - 1);
stop ->
fun() -> stop end
end;
false ->
Continuation
end.
-spec drop(iterator(AVF), integer()) -> iterator(AVF).
drop(Iterator, Desired) ->
{iterator, do_drop(erlang:element(2, Iterator), Desired)}.
-spec do_map(fun(() -> action(AVI)), fun((AVI) -> AVK)) -> fun(() -> action(AVK)).
do_map(Continuation, F) ->
fun() -> case Continuation() of
{continue, E, Continuation@1} ->
{continue, F(E), do_map(Continuation@1, F)};
stop ->
stop
end end.
-spec map(iterator(AVM), fun((AVM) -> AVO)) -> iterator(AVO).
map(Iterator, F) ->
{iterator, do_map(erlang:element(2, Iterator), F)}.
-spec do_append(fun(() -> action(AVQ)), fun(() -> action(AVQ))) -> fun(() -> action(AVQ)).
do_append(First, Second) ->
fun() -> case First() of
{continue, E, First@1} ->
{continue, E, do_append(First@1, Second)};
stop ->
Second()
end end.
-spec append(iterator(AVU), iterator(AVU)) -> iterator(AVU).
append(First, Second) ->
{iterator, do_append(erlang:element(2, First), erlang:element(2, Second))}.
-spec do_flatten(fun(() -> action(iterator(AVY)))) -> fun(() -> action(AVY)).
do_flatten(Continuation) ->
fun() -> case Continuation() of
{continue, E, Continuation@1} ->
(do_append(erlang:element(2, E), do_flatten(Continuation@1)))();
stop ->
stop
end end.
-spec flatten(iterator(iterator(AWC))) -> iterator(AWC).
flatten(Iterator) ->
{iterator, do_flatten(erlang:element(2, Iterator))}.
-spec flat_map(iterator(AWG), fun((AWG) -> iterator(AWI))) -> iterator(AWI).
flat_map(Iterator, F) ->
flatten(map(Iterator, F)).
-spec do_filter(fun(() -> action(AWL)), fun((AWL) -> boolean())) -> fun(() -> action(AWL)).
do_filter(Continuation, Predicate) ->
fun() -> case Continuation() of
{continue, E, Iterator} ->
case Predicate(E) of
true ->
{continue, E, do_filter(Iterator, Predicate)};
false ->
(do_filter(Iterator, Predicate))()
end;
stop ->
stop
end end.
-spec filter(iterator(AWO), fun((AWO) -> boolean())) -> iterator(AWO).
filter(Iterator, Predicate) ->
{iterator, do_filter(erlang:element(2, Iterator), Predicate)}.
-spec do_cycle(fun(() -> action(AWR)), fun(() -> action(AWR))) -> fun(() -> action(AWR)).
do_cycle(Next, Reset) ->
fun() -> case Next() of
{continue, E, Iterator} ->
{continue, E, do_cycle(Iterator, Reset)};
stop ->
(do_cycle(Reset, Reset))()
end end.
-spec cycle(iterator(AWV)) -> iterator(AWV).
cycle(Iterator) ->
{iterator,
do_cycle(erlang:element(2, Iterator), erlang:element(2, Iterator))}.
-spec do_range(integer(), integer(), integer()) -> fun(() -> action(integer())).
do_range(Current, Limit, Inc) ->
case Current =:= Limit of
true ->
fun() -> stop end;
false ->
fun() ->
{continue, Current, do_range(Current + Inc, Limit, Inc)}
end
end.
-spec range(integer(), integer()) -> iterator(integer()).
range(Start, Stop) ->
{iterator, do_range(Start, Stop, case Start < Stop of
true ->
1;
false ->
-1
end)}.
-spec find(iterator(AXD), fun((AXD) -> boolean())) -> {ok, AXD} | {error, nil}.
find(Haystack, Is_desired) ->
case (erlang:element(2, Haystack))() of
{continue, Element, Continuation} ->
case Is_desired(Element) of
true ->
{ok, Element};
false ->
find({iterator, Continuation}, Is_desired)
end;
stop ->
{error, nil}
end.