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

Ham*_*aya 3 clojure

我有一个名为some.core的命名空间,如下所示,

(ns some.core)
(defonce name-of-something :a)
Run Code Online (Sandbox Code Playgroud)

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


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

但随着上面我不断得到,

Can't intern namespace-qualified symbol
Run Code Online (Sandbox Code Playgroud)

错误.

Mic*_*zyk 5

(更新后考虑了以下评论.我将原始答案保留在横向规则下,以免删除评论的上下文.)

TL; DR修复:

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

问题是(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
Run Code Online (Sandbox Code Playgroud)

反引号或"语法引用"会发生什么'name-of-something变化'current-namespace/name-of-something,导致intern抱怨.(请注意,some.core保持不变-由于魔法治疗符号点,我相信其他符号- do,create-nsintern-也将被替换与名称空间限定的变种,但不会引起任何问题.)