Last active
November 13, 2017 22:08
-
-
Save brandonbloom/55a4fae8a5e348f0c499232a43fbac43 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; Handlers. | |
;; Approximates effect handlers without unwinding the stack. | |
;; Captures thread bindings so as to avoid "open recursion" between handlers. | |
;; Also binds `super` to bubble effect up to the next handler. | |
(def ^:dynamic super) | |
(defn bind-handler [var f] | |
(let [bindings (assoc (get-thread-bindings) #'super @var)] | |
(fn [& args] | |
(apply with-bindings* bindings f args)))) | |
(defn with-handler* [handler f] | |
(let [h (into {} (for [[var f] handler] | |
[var (bind-handler var f)]))] | |
(with-bindings* h f))) | |
(defmacro with-handler [handler & body] | |
`(with-handler* ~handler (fn [] ~@body))) | |
(defmacro handler [& impls] | |
(let [impls (conform! (s/* (s/cat :var symbol? | |
:methods (s/* seq?))) | |
impls)] | |
(into {} | |
(for [{:keys [var methods]} impls] | |
[(list 'var var) `(fn ~@methods)])))) | |
(defmacro defhandler [name & impls] | |
`(def ~name (handler ~@impls))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment