Skip to content

Instantly share code, notes, and snippets.

@HakimCassimallyBBC
Created July 25, 2017 11:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HakimCassimallyBBC/ec02664da71f906f08aaa90b2fe0a4dd to your computer and use it in GitHub Desktop.
Save HakimCassimallyBBC/ec02664da71f906f08aaa90b2fe0a4dd to your computer and use it in GitHub Desktop.
FSM programme flow, allowing pure single-stepping through a branching pipeline
(ns scratch.scratch
(:gen-class))
(defn effect? [[k f]]
(= \! (last (name k))))
(defn if? [[k f]]
(= :if k))
(defn step [model fsm]
(let [[k f & fsm'] fsm]
(cond
(k model) (recur model fsm')
(effect? [k f])
(try
[(assoc model k (f model)) fsm']
(catch Exception e
[(assoc model :error e) fsm']))
(if? [k f])
(let [[true-path false-path] fsm']
(if (f model)
[model true-path]
[model false-path]))
:else [(assoc model k (f model)) fsm'])))
;; so, what does this look like in action?
(defn error? [{error :error}] (some? error))
(defn correct? [{answer :answer!}] (= answer "7"))
(defn question [model] "What number am I thinking of?")
(defn ask-question [{question :question :as model}]
(println question)
(read-line))
(defn error-response [{error :error}]
"There was an error!")
(defn correct-response [model]
"That was the right answer!")
(defn incorrect-response [model]
"NO! That was the wrong answer!")
(def fsm [:question question
:answer! ask-question
:if error?
[:response error-response]
[:if correct?
[:response correct-response]
[:response incorrect-response]]])
(comment
(s/step {} fsm) ;; returns new model and next fsm
(-> (s/step {} fsm) (apply s/step) (apply s/step)) ; until empty fsm
...
;; easily test where some keys are already present
;; e.g. you can test whole flow easily, but giving
;; *sample data*, instead of with-redef'd functions
(s/step {:question "What number am I thinking of?", :answer! "6"} s/fsm))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment