Packages

Put your function in a loop until the cycle (pun intended) breaks

Current section

Files

Jump to
cycle src cycle.erl
Raw

src/cycle.erl

-module(cycle).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/cycle.gleam").
-export([continue/1, stop/1, start/2, safely_start/3]).
-export_type([next/2, limit_state/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(
" Module to conveniently run function in loop\n"
"\n"
" Use-case for this are:\n"
" - Maintain a state while sharing resources easily\n"
" - Run operation forever\n"
" - Limit cycles a loop can go through\n"
"\n"
" ```gleam\n"
" cycle.start(with: #([], 0), run: fn(state) {\n"
" let #(is, i) = state\n"
" case i < 5 {\n"
" True -> {\n"
" let i = i + 1\n"
" cycle.continue(#(list.prepend(is, i), i))\n"
" }\n"
" _ -> cycle.stop(is)\n"
" }\n"
" })\n"
" ```\n"
).
-type next(DQR, DQS) :: {continue, DQR} | {stop, DQS}.
-type limit_state(DQT) :: {limit_state, integer(), DQT}.
-file("src/cycle.gleam", 30).
?DOC(" Convenient shortcut to `Continue`.\n").
-spec continue(DQU) -> next(DQU, any()).
continue(State) ->
{continue, State}.
-file("src/cycle.gleam", 35).
?DOC(" Convenient shortcut to `Stop`.\n").
-spec stop(DQY) -> next(any(), DQY).
stop(Result) ->
{stop, Result}.
-file("src/cycle.gleam", 75).
-spec loop(DRM, fun((DRM) -> next(DRM, DRN))) -> DRN.
loop(State, Function) ->
case Function(State) of
{continue, New_state} ->
loop(New_state, Function);
{stop, Result} ->
Result
end.
-file("src/cycle.gleam", 68).
?DOC(" Start a cycle, returns a result if function tell the cycler to stop.\n").
-spec start(DRI, fun((DRI) -> next(DRI, DRJ))) -> DRJ.
start(State, Function) ->
loop(State, Function).
-file("src/cycle.gleam", 44).
?DOC(" Start a cycle with guard on max cycle, returns like normal `start`, otherwise `Error(Nil)` if n-th cycle has reached the max.\n").
-spec safely_start(DRC, integer(), fun((DRC) -> next(DRC, DRD))) -> {ok, DRD} |
{error, nil}.
safely_start(State, Max, Function) ->
start(
{limit_state, 0, State},
fun(State@1) -> case erlang:element(2, State@1) =< Max of
true ->
case Function(erlang:element(3, State@1)) of
{continue, Inner_state} ->
{continue,
{limit_state,
erlang:element(2, State@1) + 1,
Inner_state}};
{stop, Result} ->
stop({ok, Result})
end;
_ ->
stop({error, nil})
end end
).