如果你看一下Clojure中LispReader类的函数syntaxQuote(Object form)的语法:
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L1011。
ISeq seq = RT.seq(form);
if(seq == null)
ret = RT.cons(LIST,null);
else
ret = RT.list(SEQ, RT.cons(CONCAT, sqExpandList(seq)));
你会发现`(~@'(some list))被解读为:
(clojure.core/seq
(clojure.core/concat
(clojure.core/list (quote clojure.core/some))
(clojure.core/list (quote clojure.core/list))))
这段代码在 REPL 中的评估结果为:
=> (some list)
仅看 ` 的效果就可以了解它的作用
`s => user/s
``s
=> (quote user/s)
```s
=> (clojure.core/seq
(clojure.core/concat
(clojure.core/list (quote quote))
(clojure.core/list (quote user/s))))
````s
=>
(clojure.core/seq
(clojure.core/concat
(clojure.core/list (quote clojure.core/seq))
(clojure.core/list
(clojure.core/seq
(clojure.core/concat
(clojure.core/list (quote clojure.core/concat))
(clojure.core/list
(clojure.core/seq
(clojure.core/concat
(clojure.core/list (quote clojure.core/list))
(clojure.core/list
(clojure.core/seq
(clojure.core/concat
(clojure.core/list (quote quote))
(clojure.core/list (quote quote))))))))
(clojure.core/list
(clojure.core/seq
(clojure.core/concat
(clojure.core/list (quote clojure.core/list))
(clojure.core/list
(clojure.core/seq
(clojure.core/concat
(clojure.core/list (quote quote))
(clojure.core/list (quote user/s)))))))))))))
现在需要添加拼接功能。
````~s => (clojure.core/seq
(clojure.core/concat
(clojure.core/list (quote quote))
(clojure.core/list (quote user/s))))
````~~s => (quote user/s)
所以,有哪些需要注意的事项呢?
- Clojure编写者不会像读取宏一样呈现引号,因此对于数组、集合等,它会给出
(quote s)
而不是's
。
反引号宏读取器不会简化列表/引号匹配。仅引用的列表和单个条目的连接应立即执行,得到
````~~s => ''s.
- 如果您在列表、数组或集合上进行反引号处理,问题会变得更加严重... ;)
问题在于`s`不是`'s`。
如果我没记错,在LISP中,`s`会作为结果给出`'s`。;)
管理精简版本的一种可能性如下所示
(clojure.core/seq
(clojure.core/concat
(clojure.core/list (quote quote))
(clojure.core/list (quote user/s))))
在宏生成过程中可能会更改
(seq 'user/s)
但是!!!结果是一个序列,可以说是一个惰性序列,而不是'user/s'。
让我们尝试在````s上进行。简化后会得到:
(seq '(clojure.core/seq 'user/s))
结果等价于
''的
,但它不是同一个对象。
另一件事,我们必须将(引文...)的
toString
处理为“...”。
与LISP相反,
'的
是
s
和` s是user/s !!!
对于宏管理,它会发生很多变化......说's在执行命名空间中,`s在编译命名空间中,由阅读器执行。
\
`(some list)而不是
`(some list)。这可能会被计算为
`(clojure.core/some clojure.core/list)`。由于符号已经完全限定,所以符号解析不是问题。 - Qudit