有没有办法以SBCL中的清晰方式打印评估嵌套语法引号的结果?在编写宏时,在调试嵌套语法引号时,这将非常有用.例如,在Clojure 1.8中,
(let [x '(1 2)] ``(~~@x))
Run Code Online (Sandbox Code Playgroud)
评估为
(clojure.core/seq (clojure.core/concat (clojure.core/list 1 2)))
Run Code Online (Sandbox Code Playgroud)
在SBCL 1.3.6中,等效表达式
(let ((x '(1 2))) ``(,,@x))
Run Code Online (Sandbox Code Playgroud)
评估更加清晰
`(,1 ,2)
Run Code Online (Sandbox Code Playgroud)
表达式越复杂,差异越大.是否有任何Clojure软件包或其他方法可以帮助解决这种情况?目前,我发现调试复杂语法引号的最好方法是将它们转换为Common Lisp,但这是一种相当荒谬和缓慢的方法.
如果您查看 Clojure 的 LispReader 类中的函数语法Quote(Object form):\n https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L1011
\n\nISeq seq = RT.seq(form);\nif(seq == null)\n ret = RT.cons(LIST,null);\nelse\n ret = RT.list(SEQ, RT.cons(CONCAT, sqExpandList(seq)));\n
Run Code Online (Sandbox Code Playgroud)\n\n你会看到 `(~@\'(some list)) 读作:
\n\n(clojure.core/seq\n (clojure.core/concat\n (clojure.core/list (quote clojure.core/some))\n (clojure.core/list (quote clojure.core/list))))\n
Run Code Online (Sandbox Code Playgroud)\n\nREPL 将其评估为:
\n\n=> (some list)\n
Run Code Online (Sandbox Code Playgroud)\n\n单独看一下`的效果就可以了
\n\n`s => user/s ; it\'s the ref of the symbol ok\n``s \n=> (quote user/s) ; it\'s the quoted ref \n```s\n=> (clojure.core/seq ; now we manage a back-tick on a list\n (clojure.core/concat\n (clojure.core/list (quote quote)) \n (clojure.core/list (quote user/s))))\n````s\n=> \n(clojure.core/seq ; oups! always a list we add a layer\n (clojure.core/concat\n (clojure.core/list (quote clojure.core/seq))\n (clojure.core/list\n (clojure.core/seq\n (clojure.core/concat\n (clojure.core/list (quote clojure.core/concat))\n (clojure.core/list\n (clojure.core/seq\n (clojure.core/concat\n (clojure.core/list (quote clojure.core/list))\n (clojure.core/list\n (clojure.core/seq\n (clojure.core/concat\n (clojure.core/list (quote quote))\n (clojure.core/list (quote quote))))))))\n (clojure.core/list\n (clojure.core/seq\n (clojure.core/concat\n (clojure.core/list (quote clojure.core/list))\n (clojure.core/list\n (clojure.core/seq\n (clojure.core/concat\n (clojure.core/list (quote quote))\n (clojure.core/list (quote user/s)))))))))))))\n
Run Code Online (Sandbox Code Playgroud)\n\n现在添加拼接
\n\n````~s => (clojure.core/seq ; same as ```s\n (clojure.core/concat\n (clojure.core/list (quote quote)) \n (clojure.core/list (quote user/s))))\n````~~s => (quote user/s) ; same as ``s\n
Run Code Online (Sandbox Code Playgroud)\n\n那么有什么评论呢
\n\n(quote s)
不是\'s
. 这是针对数组、集合等完成的。反引号宏读取器不会简化列表/引用匹配。仅引用列表和单个条目的串联应立即执行,给出
\n\n````~~s => \'\'s。
问题是 `s 不是 \'s。
\n\n如果我记得在 LISP `s 中给出了 \'s 作为结果。;)
\n\n可以查看管理简化版本的可能性,以便
\n\n(clojure.core/seq\n (clojure.core/concat\n (clojure.core/list (quote quote)) \n (clojure.core/list (quote user/s))))\n
Run Code Online (Sandbox Code Playgroud)\n\n可以在宏生成中更改为
\n\n(seq \'user/s)\n
Run Code Online (Sandbox Code Playgroud)\n\n但!!!结果是一个序列,比如说惰性序列,而不是\'user/s
。
让我们尝试一下````。简化会给出:
\n\n(seq \'(clojure.core/seq \'user/s))\n
Run Code Online (Sandbox Code Playgroud)\n\n结果相当于\'\'s
,但不是同一个对象。
另一件事,我们必须将toString
of (quote ...) 管理为 \'...
与 LISP 相反的\'s
是s
,`s 是 user/s!
而对于宏管理,它做了很多改变...\xc2\xa0说\'s在执行命名空间,`s在编译命名空间,由读者执行。
\n