-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, index/1, iterate/2, take_while/2, drop_while/2, scan/3, zip/2]). -export_type([action/1, iterator/1, step/2]). -type action(AYJ) :: stop | {continue, AYJ, fun(() -> action(AYJ))}. -opaque iterator(AYK) :: {iterator, fun(() -> action(AYK))}. -type step(AYL, AYM) :: {next, AYL, AYM} | done. -spec do_unfold(AYP, fun((AYP) -> step(AYQ, AYP))) -> fun(() -> action(AYQ)). do_unfold(Initial, F) -> fun() -> case F(Initial) of {next, X, Acc} -> {continue, X, do_unfold(Acc, F)}; done -> stop end end. -spec unfold(AYU, fun((AYU) -> step(AYV, AYU))) -> iterator(AYV). unfold(Initial, F) -> {iterator, do_unfold(Initial, F)}. -spec repeatedly(fun(() -> AYZ)) -> iterator(AYZ). repeatedly(F) -> unfold(nil, fun(_) -> {next, F(), nil} end). -spec repeat(AZB) -> iterator(AZB). repeat(X) -> repeatedly(fun() -> X end). -spec from_list(list(AZD)) -> iterator(AZD). 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(AZG)), AZI, fun((AZG, AZI) -> AZI)) -> AZI. do_fold(Continuation, Initial, F) -> case Continuation() of {continue, Element, Iterator} -> do_fold(Iterator, F(Element, Initial), F); stop -> Initial end. -spec fold(iterator(AZJ), AZL, fun((AZJ, AZL) -> AZL)) -> AZL. 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(AZO)) -> list(AZO). to_list(Iterator) -> gleam@list:reverse(fold(Iterator, [], fun(E, Acc) -> [E | Acc] end)). -spec step(iterator(AZR)) -> step(AZR, iterator(AZR)). step(Iterator) -> case (erlang:element(2, Iterator))() of stop -> done; {continue, E, A} -> {next, E, {iterator, A}} end. -spec do_take(fun(() -> action(AZW)), integer(), list(AZW)) -> list(AZW). 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(BAA), integer()) -> list(BAA). take(Iterator, Desired) -> do_take(erlang:element(2, Iterator), Desired, []). -spec do_drop(fun(() -> action(BAD)), integer()) -> fun(() -> action(BAD)). 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(BAG), integer()) -> iterator(BAG). drop(Iterator, Desired) -> {iterator, do_drop(erlang:element(2, Iterator), Desired)}. -spec do_map(fun(() -> action(BAJ)), fun((BAJ) -> BAL)) -> fun(() -> action(BAL)). 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(BAN), fun((BAN) -> BAP)) -> iterator(BAP). map(Iterator, F) -> {iterator, do_map(erlang:element(2, Iterator), F)}. -spec do_append(fun(() -> action(BAR)), fun(() -> action(BAR))) -> fun(() -> action(BAR)). 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(BAV), iterator(BAV)) -> iterator(BAV). append(First, Second) -> {iterator, do_append(erlang:element(2, First), erlang:element(2, Second))}. -spec do_flatten(fun(() -> action(iterator(BAZ)))) -> fun(() -> action(BAZ)). 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(BBD))) -> iterator(BBD). flatten(Iterator) -> {iterator, do_flatten(erlang:element(2, Iterator))}. -spec flat_map(iterator(BBH), fun((BBH) -> iterator(BBJ))) -> iterator(BBJ). flat_map(Iterator, F) -> flatten(map(Iterator, F)). -spec do_filter(fun(() -> action(BBM)), fun((BBM) -> boolean())) -> fun(() -> action(BBM)). 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(BBP), fun((BBP) -> boolean())) -> iterator(BBP). filter(Iterator, Predicate) -> {iterator, do_filter(erlang:element(2, Iterator), Predicate)}. -spec do_cycle(fun(() -> action(BBS)), fun(() -> action(BBS))) -> fun(() -> action(BBS)). 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(BBW)) -> iterator(BBW). 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(BCE), fun((BCE) -> boolean())) -> {ok, BCE} | {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. -spec do_index(fun(() -> action(BCI)), integer()) -> fun(() -> action({integer(), BCI})). do_index(Continuation, Next) -> fun() -> case Continuation() of {continue, E, Continuation@1} -> {continue, {Next, E}, do_index(Continuation@1, Next + 1)}; stop -> stop end end. -spec index(iterator(BCL)) -> iterator({integer(), BCL}). index(Iterator) -> {iterator, do_index(erlang:element(2, Iterator), 0)}. -spec iterate(BCO, fun((BCO) -> BCO)) -> iterator(BCO). iterate(Initial, F) -> unfold(Initial, fun(Element) -> {next, Element, F(Element)} end). -spec do_take_while(fun(() -> action(BCQ)), fun((BCQ) -> boolean())) -> fun(() -> action(BCQ)). do_take_while(Continuation, Predicate) -> fun() -> case Continuation() of stop -> stop; {continue, E, Next} -> case Predicate(E) of false -> stop; true -> {continue, E, do_take_while(Next, Predicate)} end end end. -spec do_scan(fun(() -> action(BCT)), BCV, fun((BCT, BCV) -> BCV)) -> fun(() -> action(BCV)). do_scan(Continuation, Accumulator, F) -> fun() -> case Continuation() of {continue, El, Next} -> Accumulated = F(El, Accumulator), {continue, Accumulated, do_scan(Next, Accumulated, F)}; stop -> stop end end. -spec do_zip(fun(() -> action(BCX)), fun(() -> action(BCZ))) -> fun(() -> action({BCX, BCZ})). do_zip(Left, Right) -> fun() -> case Left() of stop -> stop; {continue, El_left, Next_left} -> case Right() of stop -> stop; {continue, El_right, Next_right} -> {continue, {El_left, El_right}, do_zip(Next_left, Next_right)} end end end. -spec take_while(iterator(BDC), fun((BDC) -> boolean())) -> iterator(BDC). take_while(Iterator, Predicate) -> {iterator, do_take_while(erlang:element(2, Iterator), Predicate)}. -spec do_drop_while(fun(() -> action(BDF)), fun((BDF) -> boolean())) -> action(BDF). do_drop_while(Continuation, Predicate) -> case Continuation() of stop -> stop; {continue, E, Next} -> case Predicate(E) of false -> {continue, E, Next}; true -> do_drop_while(Next, Predicate) end end. -spec drop_while(iterator(BDI), fun((BDI) -> boolean())) -> iterator(BDI). drop_while(Iterator, Predicate) -> {iterator, fun() -> do_drop_while(erlang:element(2, Iterator), Predicate) end}. -spec scan(iterator(BDL), BDN, fun((BDL, BDN) -> BDN)) -> iterator(BDN). scan(Iterator, Initial, F) -> {iterator, do_scan(erlang:element(2, Iterator), Initial, F)}. -spec zip(iterator(BDP), iterator(BDR)) -> iterator({BDP, BDR}). zip(Left, Right) -> {iterator, do_zip(erlang:element(2, Left), erlang:element(2, Right))}.