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

时间:2013-07-23 03:14:57

标签: clojure read-eval-print-loop apostrophe backticks

我对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)解析为各自的var,而反引号允许符号解析为var(但不评估)到var内的值)。这准确吗?
  2. 非引号符号(〜)到底在做什么?它是否将var评估为其实际值(即函数对象的+符号和数字对象的x符号)?如果你能用Clojure的READ-COMPILE-EVAL阶段来解释这一点,那也会有所帮助。

2 个答案:

答案 0 :(得分:30)

当您使用'引用某个集合时,将在您输入时完全引用该符号名称。

'(+ 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")

当您在~内使用`时,表单将不会被引用。这有助于构建宏,其中宏使用其定义的命名空间中的符号以及使用它的命名空间中的符号。

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

最后,你可以取消引用拼接引用的整个集合。

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

请参见x es可以作为名称空间限定符号列表传递,并且已经拼接到另一个列表中。您不能在反引号引用的集合之外使用~~@

答案 1 :(得分:2)

Backquote是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代码。

Backquote是Clojure数据的模板语言(列表,数组等)。