Skip to content

Instantly share code, notes, and snippets.

@hiredman

hiredman/foo.clj Secret

Created November 21, 2018 00:57
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 hiredman/fbade00f1641dbcb62a0feee2964495e to your computer and use it in GitHub Desktop.
Save hiredman/fbade00f1641dbcb62a0feee2964495e to your computer and use it in GitHub Desktop.
(defmacro defpoly [n]
`(defmulti ~n (let [preds# (atom ())]
(with-meta
(fn [& args#]
(loop [[[p# v#] & ps#] @preds#]
(if p#
(if (apply p# args#)
v#
(recur ps#))
(throw (Exception.)))))
{:preds preds#}))))
(defmacro defpolymethod [n p args body]
(let [v (gensym)]
`(do
(swap! (:preds (meta (.dispatchFn ~n)))
conj
[~p '~v])
(defmethod ~n '~v ~args ~body))))
;; user=> (defpoly foo)
;; nil
;; user=> (defpolymethod foo even? [n] [:even n])
;; #object[clojure.lang.MultiFn 0x29fa6b65 "clojure.lang.MultiFn@29fa6b65"]
;; user=> (defpolymethod foo odd? [n] [:odd n])
;; #object[clojure.lang.MultiFn 0x29fa6b65 "clojure.lang.MultiFn@29fa6b65"]
;; user=> (foo 1)
;; [:odd 1]
;; user=> (foo 2)
;; [:even 2]
;; user=>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment