Current section
Files
Jump to
Current section
Files
src/smut.gleam
import gleam/erlang/process.{type Subject}
type Msg(state) {
Assign(state)
Update(Subject(state), fn(state) -> state)
Retrieve(Subject(state))
}
pub opaque type State(state) {
Handle(Subject(Msg(state)))
}
fn run(state: state, pipe: Subject(Msg(state))) -> Nil {
case process.receive_forever(pipe) {
Assign(new_state) -> run(new_state, pipe)
Update(return_pipe, with) -> {
process.send(return_pipe, state)
with(state) |> run(pipe)
}
Retrieve(return_pipe) -> {
process.send(return_pipe, state)
run(state, pipe)
}
}
}
pub fn new(initial_state: state) -> State(state) {
let back_channel: Subject(Subject(Msg(state))) = process.new_subject()
process.spawn(fn() {
let pipe: Subject(Msg(state)) = process.new_subject()
process.send(back_channel, pipe)
run(initial_state, pipe)
})
let pipe = process.receive_forever(back_channel)
Handle(pipe)
}
pub fn set(new: state, handle: State(state)) {
let Handle(send) = handle
process.send(send, Assign(new))
}
pub fn get(handle: State(state)) -> state {
let return: Subject(state) = process.new_subject()
let Handle(send) = handle
process.send(send, Retrieve(return))
process.receive_forever(return)
}