Put your function in a loop until the cycle (pun intended) breaks
gleam
at master 80 lines 2.2 kB view raw
1//// Module to conveniently run function in loop 2//// 3//// Use-case for this are: 4//// - Maintain a state while sharing resources easily 5//// - Run operation forever 6//// - Limit cycles a loop can go through 7//// 8//// ```gleam 9//// cycle.start(with: #([], 0), run: fn(state) { 10//// let #(is, i) = state 11//// case i < 5 { 12//// True -> { 13//// let i = i + 1 14//// cycle.continue(#(list.prepend(is, i), i)) 15//// } 16//// _ -> cycle.stop(is) 17//// } 18//// }) 19//// ``` 20 21/// Message to the cycler if the cycle should continue or stop with a result. 22pub type Next(state, result) { 23 /// Continue the cycle with new state. 24 Continue(state) 25 /// Stop the cycle with a result. 26 Stop(result) 27} 28 29/// Convenient shortcut to `Continue`. 30pub fn continue(state: state) -> Next(state, result) { 31 Continue(state) 32} 33 34/// Convenient shortcut to `Stop`. 35pub fn stop(result: result) -> Next(state, result) { 36 Stop(result) 37} 38 39type LimitState(state) { 40 LimitState(nth_cycle: Int, state: state) 41} 42 43/// Start a cycle with guard on max cycle, returns like normal `start`, otherwise `Error(Nil)` if n-th cycle has reached the max. 44pub fn safely_start( 45 with state: state, 46 max_cycle max: Int, 47 run function: fn(state) -> Next(state, result), 48) -> Result(result, Nil) { 49 // no one except me and god can understand this piece of snippet 50 // but now only god can understand whatever bullshit happens in here 51 start(LimitState(0, state), fn(state) { 52 case state.nth_cycle <= max { 53 True -> 54 case function(state.state) { 55 Continue(inner_state) -> 56 Continue(LimitState( 57 state: inner_state, 58 nth_cycle: state.nth_cycle + 1, 59 )) 60 Stop(result) -> stop(Ok(result)) 61 } 62 _ -> stop(Error(Nil)) 63 } 64 }) 65} 66 67/// Start a cycle, returns a result if function tell the cycler to stop. 68pub fn start( 69 with state: state, 70 run function: fn(state) -> Next(state, result), 71) -> result { 72 loop(state, function) 73} 74 75fn loop(state: state, function: fn(state) -> Next(state, result)) -> result { 76 case function(state) { 77 Continue(new_state) -> loop(new_state, function) 78 Stop(result) -> result 79 } 80}