Skip to content

Instantly share code, notes, and snippets.

@aboekhoff
Created April 8, 2010 17:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aboekhoff/360303 to your computer and use it in GitHub Desktop.
Save aboekhoff/360303 to your computer and use it in GitHub Desktop.
(ns state.clj)
(comment
(def f
(statefully
x <- (*read*)
(*write* 42)
y <- (*read*)
(*update* str " was frobnicated!")
(return [x y])))
(f :stateless) => [[:stateless 42] "42 was frobnicated"])
(defn >> [mv f]
(fn [s]
(let [[_ s*] (mv s)]
(f s*))))
(defn >>= [mv f]
(fn [s]
(let [[v s*] (mv s)]
((f v) s*))))
(defn return [v] (fn [s] [v s]))
(defn parse:<-
([] [])
([x] [x])
([x y] [x y])
([x y z & more]
(lazy-seq
(if (= y '<-)
(cons ['<- x z] (apply parse:<- more))
(cons x (apply parse:<- y z more))))))
(defn do-state* [x & xs]
(if-not (seq xs)
x
(cond
(= :let x) `(let ~(first xs) ~(apply do-state* (rest xs)))
(not (vector? x)) `(>> ~x ~(apply do-state* xs))
:else `(>>= ~(last x)
(fn [~(second x)]
~(apply do-state* xs))))))
(defmacro statefully [& steps]
(apply do-state* (apply parse:<- steps)))
(defn *read* [& xs]
(fn [s]
(if (seq xs)
[(get-in s xs) s]
[s s])))
(defn *write* [x]
(fn [s] [s x]))
(defn *update* [f & args]
(fn [s] [s (apply f s args)]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment