Clojure - 引用混乱

时间:2012-01-03 04:32:23

标签: macros clojure lisp

对于非常模糊的标题抱歉:)

我是宏的新手,我很难理解这两个陈述之间的区别:

`(+ 1 2 ~(+ 2 3)) ; => (clojure.core/+ 1 2 5)
'(+ 1 2 ~(+ 2 3)) ; => (+ 1 2 (clojure.core/unquote (+ 2 3)))

当我在没有取消引用的情况下运行它们时,除了排位赛之外它们看起来相当相同吗?

`(+ 1 2 (+ 2 3)) ; => (clojure.core/+ 1 2 (clojure.core/+ 2 3))
'(+ 1 2 (+ 2 3)) ; => (+ 1 2 (+ 2 3))

所以基本上我对`vs'感到困惑。我的理解是他们都引用了列表中的所有内容,这就是为什么我不确定为什么unquoting行为不同。基本上`表现得像我希望的那样'和'表现。

谢谢!

2 个答案:

答案 0 :(得分:10)

简短的回答是,不引用只能在反引号中起作用。在正常的引用表达式中,所有内容 - 包括~和内部/后面的所有内容 - 都是按原样传递的,而在反引号表达式中,~内部/后面的所有内容都会被评估(但其他所有内容都保持未评估状态) )。所以,不,不是反引号表达式中的所有内容都不会被评估 - 您可以在其中使用~,将其用作一种模板,您可以使用~填充空白。

编辑:引用(双关语)与您的问题相关的documentation

引用:

Quote (')
'form => (quote form)

和(来自special forms部分):

  

(引用表格)产生未评估的表格。

user=> '(a b c)
(a b c)
  

注意没有尝试调用函数a。返回值   是3个符号的列表。

语法 - 引用(也称为quasiquote,反引号):

  

对于Lists / Vectors / Sets / Maps,syntax-quote建立了一个模板   相应的数据结构。在模板内,不合格   表单的行为就像递归语法引用一样,但表单可以   通过无限制地限定他们来免除这种递归引用   或unquote-splicing,在这种情况下,它们将被视为表达式   并在模板中按其值或值序列替换,   分别

答案 1 :(得分:4)

尝试对前两个表达式的结果运行eval。第一个,使用`,“扩展”到(+ 1 2 3),很好地评估为6.第二个,','扩展“到(+ 1 2 (unquote (+ 1 2))),并且unquote在该上下文中无效,因为你'再也不在报价内了!所以这完全没有评估。

基本上'和'之间存在两个不同之处:

  • `namespace-qualifies everything
  • `允许取消引用