在加载名称空间之前预先定义变量

时间:2011-08-27 02:25:46

标签: clojure

我有一个名为some.core的命名空间,其中包含以下内容,

(ns some.core)
(defonce name-of-something :a)

然后从leiningen插件我想在加载命名空间之前预定义名称,以便在加载命名空间时已经定义了defonce将不定义它。


    (eval-in-project project
                     `(do (create-ns 'some.core)
                          (intern 'some.core 'name-of-something :b)))

但随着上述情况,我一直在努力,

Can't intern namespace-qualified symbol

错误。

2 个答案:

答案 0 :(得分:5)

(已更新以考虑以下评论。我将原始答案保留在水平线规则下,以便不删除评论的上下文。)

TL; DR修复:

`(do ... (intern 'some.core '~'name-of-something :b))
                          ; ^- note the '~'

问题是(do ...)形式是语法引用的(引用反引号而不是单引号),因此其中的符号被命名空间限定的变体替换(在解析后确定哪个命名空间,他们应该合格)。这不包括已经命名空间限定的符号以及包含点的符号。

上面有问题的符号是name-of-something - 无点且不合格。要纠正这种情况,您可以将'name-of-something替换为'~'name-of-something;第一个引用包含在syntax-quote的输出中,tilde使得紧随其后的表单的值被包含在语法引用区域的扩展中,最后'name-of-something是表单本身,评估为(不合格)符号name-of-something

如果不需要取消引用,用单引号替换反引号也可以解决问题。 (最终解决方案 - 完整性提到 - 将手动构建表单:(list 'do ...)。)


(原始答案如下。)

您需要将反引号更改为单引号:

`(do (create-ns 'some.core) ...)
; change to
'(do (create-ns 'some.core) ...)
^- note the quote

反引号或“语法引用”会导致'name-of-something'current-namespace/name-of-something引发,导致intern投诉。 (请注意some.core保持不变 - 由于符号中点的魔法处理,我相信。其他符号 - docreate-nsintern - 也是替换为名称空间限定的变体,但这不会导致任何问题。)

答案 1 :(得分:0)

另一个选择是首先使用defonce加载命名空间,然后使用alter-var-root更改它。

两者都是相当疯狂的解决方法,但你要问的是开始时非常疯狂。