Skip to content

Instantly share code, notes, and snippets.

@claj
Last active March 17, 2016 10:38
Show Gist options
  • Save claj/b0ed0d547f8b6ddfaa41 to your computer and use it in GitHub Desktop.
Save claj/b0ed0d547f8b6ddfaa41 to your computer and use it in GitHub Desktop.
state in go-loop
(ns world.core
(:require [clojure.core.async :refer [go chan >! <! <!! put! timeout close!]]))
(defn apply-to-fsm
[[state _] event]
(case [state event]
[:init :create] [:running [:allocate :run]]
[:running :stop] [:stopped [:stop]]
[:running :start] [:running []]
[:stopped :start] [:started [:run]]
[:stopped :stop] [:stopped []]
[:started :destroy] [:init [:stop :release]]
[:stopped :destroy] [:init [:release]]
;; unknown state
[:crashed [:die]]))
(def incoming [:create :start :stop :start :destroy])
;; the side-effects (reductions cannot be used a transducer)
(mapcat second (reductions apply-to-fsm [:init []] incoming))
;; => (:allocate :run :stop :run :stop :release)
(def c (chan 10))
(def outchan (chan 10 (mapcat second)))
;; the loop holds the state
(go
(loop [state [:init []]
incoming-command (<! c)]
(let [new-state (apply-to-fsm state incoming-command)]
(>! outchan new-state)
(recur new-state (<! c)))))
(doseq [cmd incoming]
(put! c cmd))
(<!! (timeout 200))
;;non-go to prevent strange printing
(close! outchan)
(<!! (clojure.core.async/into [] outchan))
;; => [:allocate :run :stop :run :stop :release]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment