Current section

Files

Jump to
zlist src zlist_st.erl
Raw

src/zlist_st.erl

-module(zlist_st).
-export([
map/2,
filter/2,
filtermap/2,
flatmap/2,
over/3,
dropwhen/2,
dropwhile/2,
append/2,
ciclyc/1,
empty/0,
seq/2,
seq/3,
recurrent/2,
foreach/3,
fold/4,
take/3,
takewhile/3,
take_by/2,
from_list/1,
to_list/2
]).
-type zlist_st(A, St) ::
fun((St) ->
{maybe_improper_list(A, zlist_st(A, St)), St} |
{[], St}
).
-type empty_zlist_st(St) :: fun((St) -> {[], St}).
-export_type([
zlist_st/2,
empty_zlist_st/1
]).
%% =============================================================================
%% API functions
%% =============================================================================
-spec empty() -> empty_zlist_st(St :: any()).
empty() ->
fun(R) -> {[], R} end.
-spec seq(From, To) -> zlist_st(integer(), St :: any()) when
From :: integer(),
To :: integer().
seq(First, Last) when is_integer(First), is_integer(Last), First-1 =< Last ->
seq_(First, Last).
seq_(Curr, Last) ->
fun(St) ->
case Curr > Last of
true -> {[], St};
false -> {[Curr] ++ seq_(Curr+1, Last), St}
end
end.
-spec seq(From, To, Incr) -> zlist_st(integer(), St :: any()) when
From :: integer(),
To :: integer(),
Incr :: integer().
seq(First, Last, Inc) when is_integer(First), is_integer(Last), is_integer(Inc) ->
if
Inc > 0, First - Inc =< Last;
Inc < 0, First - Inc >= Last ->
N = (Last - First + Inc) div Inc,
seq_(N, First, Inc);
Inc =:= 0, First =:= Last ->
seq_(1, First, Inc)
end.
seq_(N, X, D) ->
fun(St) ->
case N of
0 -> {[], St};
_ -> {[X] ++ seq_(N-1, X+D, D), St}
end
end.
-spec map(fun((A) -> B), zlist_st(A, St)) -> zlist_st(B, St).
map(Fun, ZlistSt) ->
fun(St) ->
case ZlistSt(St) of
{[Data|Next], St2} ->
{[Fun(Data)] ++ map(Fun, Next), St2};
Done -> Done
end
end.
-spec filter(fun((A) -> boolean()), zlist_st(A, St)) -> zlist_st(A, St).
filter(Fun, ZlistSt) ->
fun(St) ->
case ZlistSt(St) of
{[Data|Next], St2} ->
case Fun(Data) of
true -> {[Data] ++ filter(Fun, Next), St2};
false -> (filter(Fun, Next))(St2)
end;
Done -> Done
end
end.
-spec filtermap(fun((A) -> {true, B} | false), zlist_st(A, St)) -> zlist_st(B, St).
filtermap(Fun, ZlistSt) ->
fun(St) ->
case ZlistSt(St) of
{[Data|Next], St2} ->
case Fun(Data) of
{true, Data2} -> {[Data2] ++ filtermap(Fun, Next), St2};
false -> (filtermap(Fun, Next))(St2)
end;
Done -> Done
end
end.
-spec fold(fun((A, S) -> S), S, zlist_st(A, St), St) -> {S, St}.
fold(Fun, State, ZlistSt, St) ->
case ZlistSt(St) of
{[Data|Next], St2} ->
fold(Fun, Fun(Data, State), Next, St2);
{[], St2} -> {State, St2}
end.
-spec flatmap(fun((A) -> zlist_st(B, St)), zlist_st(A, St)) -> zlist_st(B, St).
flatmap(Fun, Zlist) ->
fun(St) ->
case Zlist(St) of
{[Data|Next], St2} ->
(append(Fun(Data), flatmap(Fun, Next)))(St2);
Done -> Done
end
end.
-spec over(fun((A,S) -> {B, S}), S, zlist_st(A, St)) -> zlist_st(B, St).
over(Fun, S, ZlistSt) ->
fun(St) ->
case ZlistSt(St) of
{[Data|Next], St2} ->
{Value, S2} = Fun(Data, S),
{[Value] ++ over(Fun, S2, Next), St2};
Done -> Done
end
end.
-spec dropwhen(fun((A) -> boolean()), zlist_st(A, St)) -> zlist_st(A, St).
dropwhen(Fun, ZlistSt) ->
fun(St) ->
case ZlistSt(St) of
{[Data|Next], St2} ->
case Fun(Data) of
true -> {[], St2};
false -> {[Data] ++ dropwhen(Fun, Next), St2}
end;
Done -> Done
end
end.
-spec dropwhile(fun((A) -> boolean()), zlist_st(A, St)) -> zlist_st(A, St).
dropwhile(Fun, ZlistSt) ->
fun(St) ->
case ZlistSt(St) of
{[Data|Next], St2}=R ->
case Fun(Data) of
true -> (dropwhile(Fun, Next))(St2);
false -> R
end;
Done -> Done
end
end.
-spec append(zlist_st(A, St), zlist_st(B, St)) -> zlist_st(A|B, St).
append(Zlist1, Zlist2) ->
fun(St) ->
case Zlist1(St) of
{[Data|Next], St2} -> {[Data] ++ append(Next, Zlist2), St2};
{[], St2} -> Zlist2(St2)
end
end.
-spec ciclyc(zlist_st(A, St)) -> zlist_st(A, St).
ciclyc(Zlist) ->
(fun Loop(Zs) ->
fun(St) ->
case Zs(St) of
{[Data|Next], St2} -> {[Data] ++ Loop(Next), St2};
{[], St2} -> (ciclyc(Zlist))(St2)
end
end
end)(Zlist).
-spec from_list([A]) -> zlist_st(A, St :: any()).
from_list(List) ->
fun(St) ->
case List of
[H|T] -> {[H] ++ from_list(T), St};
[] -> {List, St}
end
end.
-spec to_list(zlist_st(A, St), St) -> {[A], St}.
to_list(Zlist, St) ->
{List, St2} = fold(fun(H, T) -> [H|T] end, [], Zlist, St),
{lists:reverse(List), St2}.
-spec recurrent(fun((A) -> A), A) -> zlist_st(A, St :: any()).
recurrent(Fun, S) ->
fun(St) ->
Next = Fun(S),
{[Next] ++ recurrent(Fun, Next), St}
end.
-spec foreach(fun((A) -> any()), zlist_st(A, St), St) -> St.
foreach(Fun, ZlistSt, St) ->
case ZlistSt(St) of
{[Data|Next], St2} ->
_ = Fun(Data),
foreach(Fun, Next, St2);
{[], St2} -> St2
end.
-spec take(N :: pos_integer(), zlist_st(A, St), St) -> {[A], zlist_st(A, St), St}.
take(N, ZlistSt, St) when N > 0 ->
take_(N, [], ZlistSt, St).
take_(0, Acc, Zs, St) -> {lists:reverse(Acc), Zs, St};
take_(C, Acc, Zs, St) ->
case Zs(St) of
{[Data|Next], St2} -> take_(C-1, [Data|Acc], Next, St2);
{[], St2} -> {lists:reverse(Acc), empty(), St2}
end.
-spec takewhile(fun((A) -> boolean()), zlist_st(A, St), St) -> {[A], zlist_st(A, St), St}.
takewhile(Fun, Zlist, St) -> takewhile_(Fun, [], Zlist, St).
takewhile_(Fun, Acc, Zs, St) ->
case Zs(St) of
{[Data|Next], St2} ->
case Fun(Data) of
true -> takewhile_(Fun, [Data|Acc], Next, St2);
false ->
NextZs = fun(S) ->
{[Data] ++ Next, S}
end,
{lists:reverse(Acc), NextZs, St2}
end;
{[], St2} -> {lists:reverse(Acc), empty(), St2}
end.
-spec take_by(N :: pos_integer(), zlist_st(A, St)) -> zlist_st([A], St).
take_by(N, Zlist) when N > 0 ->
fun(St) ->
case take(N, Zlist, St) of
{[], _EmptyZ, St2} -> {[], St2};
{List, RestZ, St2} -> {[List] ++ take_by(N, RestZ), St2}
end
end.