Skip to content

Instantly share code, notes, and snippets.

@semperos
Last active March 23, 2018 20:02
Show Gist options
  • Save semperos/3612fc515bcef06b1bd4fea9e3e5562c to your computer and use it in GitHub Desktop.
Save semperos/3612fc515bcef06b1bd4fea9e3e5562c to your computer and use it in GitHub Desktop.
Clojure Mutable Stack using clojure.lang.Volatile
(def ^:dynamic *eval-mode* :stack)
(defprotocol IVolatileStack
(vpeek [stack] "Return stack's top item.")
(vpop! [stack] "Pop top item off the stack, returning the item and mutating the underlying stack.")
(vpush! [stack item] "Push item onto top of stack. Return mutated stack."))
(extend-type clojure.lang.Volatile
IVolatileStack
(vpeek [vol] (peek @vol))
(vpop! [vol]
(let [ret (vpeek vol)]
(vswap! vol pop)
ret))
(vpush! [vol item]
(vswap! vol conj item)))
(defn eval-stack
[forms]
(let [stack (volatile! [])]
(letfn [(eval-form [form]
(if (= form ::with)
(let [b (vpop! stack)
a (vpop! stack)]
(vpush! stack (deep-merge a b)))
(vpush! stack form)))]
(loop [forms forms]
(if-let [form (first forms)]
(do
(eval-form form)
(recur (next forms)))
(vpeek stack))))))
(defn eval*
[forms]
(case *eval-mode*
:stack (eval-stack forms)
(eval-stack forms)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment