Skip to content

Instantly share code, notes, and snippets.

@scgilardi
Last active August 29, 2015 14:06
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 scgilardi/e040cd35c85cc96b9739 to your computer and use it in GitHub Desktop.
Save scgilardi/e040cd35c85cc96b9739 to your computer and use it in GitHub Desktop.
declare+
(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