Clojure:quote与syntax quote的求值顺序疑问
嘿,这个问题确实容易绕晕,我来一步步拆解这两个表达式的处理过程,你就能瞬间明白为啥结果一模一样了~
首先得先明确几个Clojure里的核心规则:
- 单引号
'x就是(quote x)的语法糖,作用是直接返回x本身,不让它被求值。 - 语法引号
x(反引号)的核心作用是生成带命名空间限定的符号,而且它会“渗透”到嵌套的表达式里,自动给所有未加限定的符号添上当前命名空间(比如你当前在user命名空间下,就会变成user/x)。 ~是解引用操作符,只能用在语法引号内部,作用是把某个表达式直接插入到语法引号生成的模板里,而不被语法引号的命名空间限定处理。
现在来看第一个表达式(~'baz)(注:你写的(~'baz)应该是输入格式问题,~`必须在语法引号内部,正确写法是外面套反引号):
- 先看内部的
'baz:它等价于(quote baz)。 - 当这个
'baz被放在语法引号里时,语法引号会“盯上”里面的baz,自动给它加上当前命名空间,所以'baz就变成了'user/baz(也就是(quote user/baz))。 - 然后
~解引用,把这个'user/baz直接插入到外层的语法引号模板里,所以整个表达式展开后就是'user/baz,也就是你看到的('user/baz)(单引号的完整写法)。
再看第二个表达式(~'`baz):
- 内部的
'baz等价于(quotebaz)。而baz本身被语法引号处理后就是user/baz,所以(quotebaz)其实就是(quote user/baz),也就是'user/baz`。 - 同样用
~解引用,把'user/baz插入到模板里,最终展开的结果自然也是'user/baz,也就是('user/baz)。
你之前误以为第一个表达式会得到('baz),是因为以为语法引号不会处理quote里面的符号,但实际上语法引号的命名空间限定是会渗透到嵌套的quote表达式里的,它不会因为有quote就“手下留情”~
内容的提问来源于stack exchange,提问作者TheChetan




