I have a namespace called some.core with the following,
(ns some.core)
(defonce name-of-something :a)
then from a leiningen plugin I would like to predefine name-of-something before loading the namespace so that when the namespace is loaded it is already defined defonce won't define it.
(eval-in-project project
`(do (create-ns 'some.core)
(intern 'some.core 'name-of-something开发者_如何学JAVA :b)))
but with the above I keep getting,
Can't intern namespace-qualified symbol
error.
(Updated to take into account the comments below. I leave the original answer under the horizontal rule so as not to remove the context of the comments.)
TL;DR fix:
`(do ... (intern 'some.core '~'name-of-something :b))
; ^- note the '~'
The problem is that the (do ...)
form is syntax-quoted (quoted with a backtick, as opposed to a single quote), so symbols inside it get replaced with namespace-qualified variants (after being resolved to determine which namespace they should be qualified with). This excludes symbols which are already namespace-qualified as well as those which contain a dot.
The problematic symbol in the above is name-of-something
-- dot-free and unqualified. To rectify the situation, you can replace 'name-of-something
with '~'name-of-something
; the first quote is included in the output of syntax-quote, the tilde causes the value of the form immediately following it to be included in the expansion of the syntax-quoted region and finally 'name-of-something
is the form itself, evaluating to the (unqualified) symbol name-of-something
:
If unquoting was unnecessary, replacing the backtick with a single quote would also solve the problem. (The final solution -- mentioned for completeness -- would be to build the form manually: (list 'do ...)
.)
(Original answer follows.)
You need to change the backtick to single quote:
`(do (create-ns 'some.core) ...)
; change to
'(do (create-ns 'some.core) ...)
^- note the quote
What happens with the backtick, or "syntax quote", is that 'name-of-something
gets munged to 'current-namespace/name-of-something
, causing intern
to complain. (Note that some.core
stays untouched -- due to magic treatment of dots in symbols, I believe. The other symbols -- do
, create-ns
and intern
-- are also replaced with namespace-qualified variants, but that doesn't cause any problems.)
Another option is to just load the namespace with the defonce first and then change it with alter-var-root.
Both are pretty crazy workarounds, but what you're asking is pretty crazy to begin with.
精彩评论