Created
March 16, 2015 04:13
-
-
Save noprompt/6d4aa092b0e2eb65c043 to your computer and use it in GitHub Desktop.
complies? macro for ClojureScript. Verifies than an object not only satisfies a protocol but implements all of it.
This file contains hidden or 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
(ns example.macros | |
(:require | |
[cljs.analyzer :as a] | |
[cljs.compiler :as c])) | |
(defmacro complies? | |
"True if x satisfies and implements all methods of a protocol. | |
Ex. | |
(defprotocol IFoo | |
(-foo [this])) | |
(deftype Foo [] | |
IFoo | |
(-foo [this])) | |
(deftype Bar [] | |
IFoo) | |
(complies? IFoo (Foo.)) | |
;; => true | |
(complies? IFoo (Bar.)) | |
;; => false | |
" | |
[psym x] | |
(let [pvar (cljs.analyzer/resolve-var | |
(dissoc &env :locals) psym) | |
pname (:name pvar) | |
pmeths (-> pvar :protocol-info :methods) | |
pprefix (cljs.core/protocol-prefix pname) | |
omkeys (mapcat | |
(fn [[pmeth psigs]] | |
(for [psig psigs] | |
(str pprefix (cljs.compiler/munge pmeth) "$arity$" (count psig)))) | |
pmeths)] | |
`(boolean | |
(and (satisfies? ~psym ~x) | |
~@(for [omkey omkeys] | |
`(.. (type ~x) -prototype ~(symbol (str "-" omkey)))))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Since ClojureScript (and Clojure) do not require a protocol implementor to fully implement a protocol,
satisfies?
can potentially lead to a false positive.complies?
is an extension ofsatisfies?
that does not suffer from this.