Macros 为什么clojure要在反引号中为名称添加名称空间限定符?

Macros 为什么clojure要在反引号中为名称添加名称空间限定符?,macros,clojure,datomic,Macros,Clojure,Datomic,我试图以编程方式构建数据日志查询,但一直遇到我将用示例函数说明的问题: (defn test-expr [attribute] `[?entity ~attribute ?value]]) 当我运行(test expr 3)时,我希望输出: [?entity 3 ?value] 但是相反,我得到了 [mynamespace/?entity 3 mynamespace/?value] 这显然不是我想要的。有没有办法告诉clojure“请引用我告诉您的列表并展开变量?”是的,有 (def

我试图以编程方式构建数据日志查询,但一直遇到我将用示例函数说明的问题:

(defn test-expr [attribute]
  `[?entity ~attribute ?value]])
当我运行(test expr 3)时,我希望输出:

 [?entity 3 ?value]
但是相反,我得到了

[mynamespace/?entity 3 mynamespace/?value]
这显然不是我想要的。有没有办法告诉clojure“请引用我告诉您的列表并展开变量?”

是的,有

(defn test-expr [attribute]
  `[~'?entity ~attribute ~'?value])
在这里,首先取消引用语法引号,然后立即再次引用符号(
~”
construct)。结果是无名称空间符号

它相当于以下内容,解释了它的工作原理:

(defn test-expr [attribute]
  `[~(quote ?entity) ~attribute ~(quote ?value)])

你要找的是Brandon Bloom的backtick图书馆

它是为您描述的确切问题而构建的。它提供了一个名为“template”的命令,该命令的工作方式类似于backtick,但没有名称空间

在Clojure中,准旋转和名称空间解析混合在一个功能中。这对于使用Clojure这样的语言编写宏有很大的好处,Clojure是一种“Lisp-1”(与Common Lisp不同,后者是一种“Lisp-2”,具有单独的函数和变量名称空间)


我也同意,最好不要将这些功能混为一谈,但这会使Clojure中宏的编写变得不那么优雅,因此我可以理解为什么它会这样工作。

至于原因,这是为了防止用户(咳嗽)通过定义与您使用的名称相同的函数和/或变量来意外破坏宏。@Cubic,同意。据我所知,这是Scheme宏和普通Lisp普通宏系统之间的某种折衷:宏定义看起来几乎完全像普通Lisp宏(这很好,因为Scheme宏更难编写),但默认情况下,存在一定程度的卫生问题-符号不是盲目捕获的,而是以名称空间作为前缀。在需要的时候(例如,对于回指宏),总是可以回到简单的替换。