-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 ).