Current section
Files
Jump to
Current section
Files
src/gens@stream.erl
-module(gens@stream).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-define(FILEPATH, "src/gens/stream.gleam").
-export([take/2, map/2, drop/2, zip/2, list_zip/2, while/2, scan/3, merge/3, fold/2, from_lazy_list/1, flatten/1, filter/2]).
-export_type([stream/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC("================== Stream ==================\n").
-type stream(HSO) :: {stream, fun(() -> HSO), fun(() -> stream(HSO))}.
-file("src/gens/stream.gleam", 12).
?DOC(" `Tail recursive` function for **take**\n").
-spec take_acc(stream(HSP), integer(), list(HSP)) -> list(HSP).
take_acc(Stream, N, Acc) ->
case N > 0 of
false ->
lists:reverse(Acc);
true ->
take_acc(
(erlang:element(3, Stream))(),
N - 1,
[(erlang:element(2, Stream))() | Acc]
)
end.
-file("src/gens/stream.gleam", 30).
?DOC(
" **Takes** a `finite` number of elements from the Stream\n"
" ```gleam\n"
" pub fn ones() -> Stream(Int) {\n"
" Stream(head: fn() { 1 }, tail: ones)\n"
" }\n"
" ```\n"
" ```gleam\n"
" ones()\n"
" |> take(5)\n"
" // -> [1, 1, 1, 1, 1]\n"
" ```\n"
).
-spec take(stream(HST), integer()) -> list(HST).
take(Stream, N) ->
take_acc(Stream, N, []).
-file("src/gens/stream.gleam", 55).
?DOC(
" **Maps** each element of the Stream\n"
" ```gleam\n"
" pub fn alt(positive: Bool) -> Stream(Int) {\n"
" Stream(\n"
" head: fn() {\n"
" case positive {\n"
" True -> 1\n"
" False -> -1\n"
" }\n"
" },\n"
" tail: fn() { alt(!positive) },\n"
" )\n"
" }\n"
" ```\n"
" ```gleam\n"
" alt(True)\n"
" |> map(fn(x) { x * 2 })\n"
" |> map(fn(x) { int.to_string(x) <> \" oranges\" })\n"
" |> take(5)\n"
" // -> [\"2 oranges\", \"-2 oranges\", \"2 oranges\", \"-2 oranges\", \"2 oranges\"]\n"
" ```\n"
).
-spec map(stream(HSW), fun((HSW) -> HSY)) -> stream(HSY).
map(Stream, F) ->
{stream,
fun() -> F((erlang:element(2, Stream))()) end,
fun() -> map((erlang:element(3, Stream))(), F) end}.
-file("src/gens/stream.gleam", 60).
?DOC(" Lazy function for getting the filtered stream's head\n").
-spec loop_head(stream(HTA), fun((HTA) -> boolean())) -> HTA.
loop_head(Stream, Pred) ->
Current = (erlang:element(2, Stream))(),
case Pred(Current) of
true ->
Current;
false ->
loop_head((erlang:element(3, Stream))(), Pred)
end.
-file("src/gens/stream.gleam", 106).
?DOC(
" **Drops** the first n elements from the Stream\n"
" ```gleam\n"
" pub fn powers() -> Stream(Int) {\n"
" Stream(head: fn() { 1 }, tail: fn() { map(powers(), fn(x) { x * 2 }) })\n"
" }\n"
" ```\n"
" ```gleam\n"
" powers() // 1, 2, 4, 8, 16..\n"
" |> drop(3)\n"
" |> take(5)\n"
" // -> [8, 16, 32, 64, 128]\n"
" ```\n"
).
-spec drop(stream(HTI), integer()) -> stream(HTI).
drop(Stream, N) ->
case N > 0 of
true ->
drop((erlang:element(3, Stream))(), N - 1);
false ->
Stream
end.
-file("src/gens/stream.gleam", 119).
?DOC(
" **Zips** two Streams togheter\n"
" ```gleam\n"
" zip(naturals(), drop(naturals(), 5))\n"
" |> take(3)\n"
" |> [#(0, 5), #(1, 6), #(2, 7)]\n"
" ```\n"
).
-spec zip(stream(HTL), stream(HTN)) -> stream({HTL, HTN}).
zip(A_stream, B_stream) ->
{stream,
fun() ->
{(erlang:element(2, A_stream))(), (erlang:element(2, B_stream))()}
end,
fun() ->
zip(
(erlang:element(3, A_stream))(),
(erlang:element(3, B_stream))()
)
end}.
-file("src/gens/stream.gleam", 130).
?DOC(
" **Zips** a list with a Stream\n"
" ```gleam\n"
" list_zip([\"a\", \"b\", \"c\"], naturals())\n"
" // -> [#(\"a\", 0), #(\"b\", 1), #(\"c\", 2)]\n"
" ```\n"
).
-spec list_zip(list(HTQ), stream(HTS)) -> list({HTQ, HTS}).
list_zip(List, Stream) ->
case List of
[] ->
[];
[X | Xs] ->
[{X, (erlang:element(2, Stream))()} |
list_zip(Xs, (erlang:element(3, Stream))())]
end.
-file("src/gens/stream.gleam", 143).
?DOC(
" **Takes** elements from the Stream until the condition is false\n"
" ```gleam\n"
" naturals()\n"
" |> while(fn(x) { x < 5 })\n"
" // -> [0, 1, 2, 3, 4]\n"
" ```\n"
).
-spec while(stream(HTV), fun((HTV) -> boolean())) -> list(HTV).
while(Stream, Condition) ->
case Condition((erlang:element(2, Stream))()) of
false ->
[];
true ->
[(erlang:element(2, Stream))() |
while((erlang:element(3, Stream))(), Condition)]
end.
-file("src/gens/stream.gleam", 162).
?DOC(
" **Scans** the Stream and reconstructs it using an accumulator\n"
" ```gleam\n"
" pub fn dummy() -> Stream(Nil) {\n"
" Stream(head: fn() { Nil }, tail: dummy)\n"
" }\n"
" ```\n"
" ```gleam\n"
" let evens: Stream(Int) = scan(dummy(), 0, fn(_, acc) { acc + 2 })\n"
" evens\n"
" |> take(5)\n"
" // -> [0, 2, 4, 6, 8]\n"
" ```\n"
).
-spec scan(stream(HTY), HUA, fun((HTY, HUA) -> HUA)) -> stream(HUA).
scan(Stream, Acc, F) ->
{stream,
fun() -> Acc end,
fun() ->
scan(
(erlang:element(3, Stream))(),
F((erlang:element(2, Stream))(), Acc),
F
)
end}.
-file("src/gens/stream.gleam", 174).
?DOC(
" **Merges** two sorted Streams\n"
" ```gleam\n"
" merge(naturals(), naturals() |> map(fn(x) { x * 2 }), int.compare)\n"
" |> take(8)\n"
" // -> [0, 0, 1, 2, 2, 3, 4, 4]\n"
" ```\n"
).
-spec merge(stream(HUC), stream(HUC), fun((HUC, HUC) -> gleam@order:order())) -> stream(HUC).
merge(Stream1, Stream2, Compare) ->
{stream,
fun() ->
case Compare(
(erlang:element(2, Stream1))(),
(erlang:element(2, Stream2))()
) of
gt ->
(erlang:element(2, Stream2))();
_ ->
(erlang:element(2, Stream1))()
end
end,
fun() ->
case Compare(
(erlang:element(2, Stream1))(),
(erlang:element(2, Stream2))()
) of
gt ->
merge(Stream1, (erlang:element(3, Stream2))(), Compare);
_ ->
merge((erlang:element(3, Stream1))(), Stream2, Compare)
end
end}.
-file("src/gens/stream.gleam", 205).
?DOC(
" **Folds** the Stream into a single value using an accumulator\n"
" ```gleam\n"
" let stream_or = fn(s: Stream(Bool)) -> Bool {\n"
" fold(s, fn(x, next) { x || next() })\n"
" }\n"
" // If at least one element is True, then the fold ends\n"
" // If all elements in the Stream are False, the fold runs infinitely\n"
" stream_or(naturals() |> map(fn(x) { x == 10 }))\n"
" // -> True\n"
" ```\n"
).
-spec fold(stream(HUG), fun((HUG, fun(() -> HUI)) -> HUI)) -> HUI.
fold(Stream, F) ->
F(
(erlang:element(2, Stream))(),
fun() -> fold((erlang:element(3, Stream))(), F) end
).
-file("src/gens/stream.gleam", 210).
?DOC(" Lazy function for getting the flattened stream's head\n").
-spec loop_flatten_head(stream(list(HUJ))) -> HUJ.
loop_flatten_head(Stream) ->
case (erlang:element(2, Stream))() of
[X | _] ->
X;
[] ->
loop_flatten_head((erlang:element(3, Stream))())
end.
-file("src/gens/stream.gleam", 256).
?DOC(
" Conversion from **LazyList** to **Stream**\n"
" ```gleam\n"
" let lazy_odds =\n"
" lazy.new()\n"
" |> lazy.filter(int.is_odd)\n"
" |> lazy.map(int.to_string)\n"
" let stream_odds = from_lazy_list(lazy_odds)\n"
" stream_odds\n"
" |> take(5)\n"
" // -> [\"1\", \"3\", \"5\", \"7\", \"9\"]\n"
" ```\n"
).
-spec from_lazy_list(gens@lazy:lazy_list(HUU)) -> stream(HUU).
from_lazy_list(Lz) ->
{stream, fun() -> case gens@lazy:take(Lz, 1) of
[] ->
erlang:error(#{gleam_error => panic,
message => <<"`panic` expression evaluated."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gens/stream"/utf8>>,
function => <<"from_lazy_list"/utf8>>,
line => 260});
[X | _] ->
X
end end, fun() -> from_lazy_list(gens@lazy:drop(Lz, 1)) end}.
-file("src/gens/stream.gleam", 239).
?DOC(
" **Flatten** a Stream of Lists\n"
" ```gleam\n"
" let repeat_stream = naturals() |> map(fn(x) { list.repeat(x, x) })\n"
" repeat_stream\n"
" |> take(5)\n"
" // -> [[], [1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]\n"
" repeat_stream\n"
" |> flatten()\n"
" |> take(10)\n"
" // -> [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]\n"
" ```\n"
).
-spec flatten(stream(list(HUQ))) -> stream(HUQ).
flatten(Stream) ->
{stream,
fun() -> loop_flatten_head(Stream) end,
fun() -> loop_flatten_tail(Stream) end}.
-file("src/gens/stream.gleam", 218).
?DOC(" Lazy function for getting the flattened stream's tail\n").
-spec loop_flatten_tail(stream(list(HUM))) -> stream(HUM).
loop_flatten_tail(Stream) ->
case (erlang:element(2, Stream))() of
[_ | Xs] ->
New_stream = {stream, fun() -> Xs end, erlang:element(3, Stream)},
flatten(New_stream);
[] ->
loop_flatten_tail((erlang:element(3, Stream))())
end.
-file("src/gens/stream.gleam", 88).
?DOC(
" **Filters** elements from the Stream\n"
" ```gleam\n"
" pub fn naturals() -> Stream(Int) {\n"
" Stream(head: fn() { 0 }, tail: fn() { map(naturals(), fn(x) { x + 1 }) })\n"
" }\n"
" ```\n"
" ```gleam\n"
" filter(naturals(), fn(x) { x % 3 == 0 })\n"
" |> take(5)\n"
" // -> [0, 3, 6, 9, 12]\n"
" ```\n"
).
-spec filter(stream(HTF), fun((HTF) -> boolean())) -> stream(HTF).
filter(Stream, Pred) ->
{stream,
fun() -> loop_head(Stream, Pred) end,
fun() -> loop_tail(Stream, Pred) end}.
-file("src/gens/stream.gleam", 69).
?DOC(" Lazy function for getting the filtered stream's tail\n").
-spec loop_tail(stream(HTC), fun((HTC) -> boolean())) -> stream(HTC).
loop_tail(Stream, Pred) ->
Current = (erlang:element(2, Stream))(),
case Pred(Current) of
true ->
filter((erlang:element(3, Stream))(), Pred);
false ->
loop_tail((erlang:element(3, Stream))(), Pred)
end.