Skip to content

Instantly share code, notes, and snippets.

@hiredman
Created February 17, 2012 23:53
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 hiredman/1856336 to your computer and use it in GitHub Desktop.
Save hiredman/1856336 to your computer and use it in GitHub Desktop.
def of deftypeddispatched
(ns cheshire.type-dispatch
(:use [clojure.pprint :only [pprint]]))
;; OMG SCARY
;; not crazy about these names
;; should use a vector instead of a map so to having deterministic
;; ordering in generated condp
(defmacro deftypedispatched
"generates macros for fast inlined type dispatching (like defmulti)"
[name]
`(do
(defmacro ~name [type# & args#]
(let [bodies# @(:cases (meta (resolve '~name)))]
(list* 'condp 'instance? type#
(concat (apply concat (for [[class# fn#] bodies#
:when (not= class# :miss)]
[class# (list* fn# type# args#)]))
(when (:miss bodies#)
[(list* (:miss bodies#) type# args#)])))))
(alter-meta! (resolve '~name) assoc :cases (atom {}))
(resolve '~name)))
(defmacro defdispatched
"generates macros for fast inlined type dispatching (like defmethod), body is
in the style of definline or defmacro"
[a-name type args & body]
(let [fn-name (symbol (str a-name "-" (if (keyword? type)
(name type)
(.getName (resolve type)))))]
`(do
(definline ~fn-name ~args
(list 'let '[~(if (keyword? type)
(first args)
(vary-meta (first args) assoc :tag type))
~(first args)
~(second args) ~(second args)]
~@body))
(swap! (:cases (meta (resolve '~a-name))) assoc ~type '~fn-name)
(resolve '~a-name))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment