-
-
Save scgilardi/e040cd35c85cc96b9739 to your computer and use it in GitHub Desktop.
declare+
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
(defmacro assert-ns | |
"Compile time assertion that *ns* is the namespace named sym." | |
[sym message] | |
(assert (= (ns-name *ns*) sym) message)) | |
(defmacro declare+ | |
"Like clojure.core/declare, but allows namespace-qualified names. | |
As is the case for ns, def, and declare forms, declare+ forms are | |
intended to appear at the top level, not nested within other forms. | |
declare+ forms containing namespace-qualified names may appear only | |
at the top-level or nested exclusively within explicit do forms. | |
Improper nesting will trigger an assertion failure at compile time. | |
Inspired by: | |
http://groups.google.com/d/msg/clojure/pKhiC82funo/eLMiPOpHTNEJ" | |
[& names] | |
(let [groups (group-by namespace names) | |
simple-names (groups nil) | |
qualified-groups (seq (dissoc groups nil)) | |
dequalify (ƒ [sym] (-> (name sym) (symbol) (with-meta (meta sym)))) | |
start-ns (ns-name *ns*) | |
nesting-error "declare+ form is improperly nested"] | |
`(do | |
~@(if simple-names | |
`[(declare ~@simple-names)]) | |
~@(if qualified-groups | |
`[~@(apply concat | |
(for [[ns-str qualified-names] qualified-groups] | |
`[(in-ns '~(symbol ns-str)) | |
(assert-ns ~(symbol ns-str) ~nesting-error) | |
(declare ~@(map dequalify qualified-names))])) | |
(in-ns '~start-ns) | |
#'~(last names)])))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment