Clojure - '(撇号)和`(反引号)之间的区别

46

我对Clojure还比较新,不确定单引号和反引号在Clojure中的区别。

(def x 5)

;; Question 1
(+ x x)  ;; evaluates to 10
'(+ x x) ;; evaluates to (+ x x)
`(+ x x) ;; evaluates to (clojure.core/+ user/x user/x)

;; Question 2
`(~+ ~x ~x) ;; evaluates to (#<core$_PLUS_ clojure.core$_PLUS_@32ee28a9> 5 5)
  1. 请纠正我如果我错了,但似乎撇号会阻止所有符号(例如+和x)解析为它们各自的变量,而反引号允许符号解析为它们的变量(但不会计算变量中的值)。这是否准确?
  2. 这里的波浪号符号(~)到底是做什么的?它是将变量评估为其实际值(例如将+符号评估为函数对象并将x符号评估为数字对象)吗?如果您可以使用Clojure的READ-COMPILE-EVAL阶段来解释这一点,那将非常有帮助。
2个回答

43
当您使用'引用一个集合时,符号名称将会被完全引用为您输入的方式。
'(+ x x) 
=> (+ x x)
(map namespace *1)
=> (nil nil nil)
'(bingo/+ lara/y user/z)
=> (bingo/+ lara/y user/z)
(map namespace *1)
=> ("bingo" "lara" "user")

使用反引号引用集合时,它尝试查找每个符号的命名空间。如果找不到命名空间,则使用当前命名空间。如果指定了命名空间,则与带有限定命名空间的'相同。

`(+ x x)
= > (clojure.core/+ user/x user/x)
(map namespace *1)
=> ("clojure.core" "user" "user")
当你在`内使用~,表单将不会被引用。这对于构建宏非常有帮助,因为该宏可以使用来自定义名字空间的符号以及来自使用它的名字空间的符号。

When you are using ~ inside ` the form will simply be unquoted. This is helpful for building macros where the macro uses symbols from the namespace it is defined in as well as symbols from the namespace where it is used.

 `(+ ~'x x)
 => (clojure.core/+ x user/x)
 `(+ ~x x)
 => (clojure.core/+ 3 user/x)

最后,您可以取消引用整个集合的引用内容并进行拼接。

 `(+ ~@`(x x))
 => (clojure.core/+ user/x user/x)

可以将两个 x 都作为命名空间限定符号的列表传递,并将它们插入到另一个列表中。你不能在非反引号引用的集合之外使用 ~~@


2
不错的回答。如果你想深入了解,这里有一篇优秀的博客文章:https://blog.8thlight.com/colin-jones/2012/05/22/quoting-without-confusion.html - Daniel Szmulewicz

2

反引号是Clojure术语中的语法引用,详见http://clojure.org/reader的描述。

在阅读过程中,`(~+ ~x ~x)扩展为生成可以引用词法环境的列表。然后编译器编译此代码。让我们看看`(~+ ~x ~x)扩展成什么,将其引号标记添加到前面:

user=> '`(~+ ~x ~x)
(clojure.core/seq (clojure.core/concat (clojure.core/list +) (clojure.core/list x) (clojure.core/list x)))

如果您只是在文本编辑器中插入此表单而不是 `(~+ ~x ~x),它将使用 + 函数和两个 x 构建列表。 因此,`(~+ ~x ~x) 扩展为构建特定结构的 Clojure 代码。
反引号是一种用于Clojure数据(列表、数组等)的模板语言。

“syntax-quote” 实际上是什么意思? - wmock
这只是Clojure文档中的一个单词。 另请参阅 https://dev59.com/6HA65IYBdhLWcg3wqAWt - monoid
3
这句话的意思是引号表示引用,但需要先解析符号:'+代表简单的加号,而`+代表'clojure.core/+',但如果你定义了(def + rest),那么`+就变成了'user/+' - 所以它在环境中被解析为什么符号。 - Hendekagon
1
Markdown问题:此答案中至少有一个未转义的反引号,导致出现问题。 - Paul Bissex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接