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

wmo*_*ock 33 clojure apostrophe backticks read-eval-print-loop

我对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)
Run Code Online (Sandbox Code Playgroud)
  1. 如果我错了,请纠正我,但在我看来,撇号阻止所有符号(即+和x)解析为它们各自的var,而反引号允许符号解析为它们的var(但不评估值在var内.这准确吗?
  2. unquote符号(〜)到底在做什么?它是否将var评估为其实际值(即函数对象的+符号和数字对象的x符号)?如果你可以用Clojure的READ-COMPILE-EVAL阶段来解释这一点,那也会有所帮助.

Leo*_*hin 31

当您引用集合时',符号名称将在您输入时完全引用.

'(+ 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")
Run Code Online (Sandbox Code Playgroud)

当您使用反引号引用集合时,它会尝试查找每个符号的命名空间.如果找不到,则使用当前命名空间.如果指定命名空间,则它'与限定命名空间的工作方式相同.

`(+ x x)
= > (clojure.core/+ user/x user/x)
(map namespace *1)
=> ("clojure.core" "user" "user")
Run Code Online (Sandbox Code Playgroud)

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

 `(+ ~'x x)
 => (clojure.core/+ x user/x)
 `(+ ~x x)
 => (clojure.core/+ 3 user/x)
Run Code Online (Sandbox Code Playgroud)

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

 `(+ ~@`(x x))
 => (clojure.core/+ user/x user/x)
Run Code Online (Sandbox Code Playgroud)

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

  • 好答案。如果您想深入了解,这里有一篇很棒的博客文章:https://blog.8thlight.com/colin-jones/2012/05/22/quoting-without-confusion.html (2认同)