漂亮的打印嵌套语法引号

Qud*_*dit 5 clojure quote

有没有办法以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,但这是一种相当荒谬和缓慢的方法.

Iva*_*rre 2

如果您查看 Clojure 的 LispReader 类中的函数语法Quote(Object form):\n https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L1011

\n\n
ISeq 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\n

REPL 将其评估为:

\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
    \n
  1. Clojure writer 不会渲染读取器宏接收到的引号,因此它给出的(quote s)不是\'s. 这是针对数组、集合等完成的。
  2. \n
  3. 反引号宏读取器不会简化列表/引用匹配。仅引用列表和单个条目的串联应立即执行,给出

    \n\n

    ````~~s => \'\'s。

  4. \n
  5. 如果您管理列表、数组或集合上的反勾,问题会更严重......;)
  6. \n
\n\n

问题是 `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

让我们尝试一下````。简化会给出:

\n\n
(seq \'(clojure.core/seq \'user/s))\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果相当于\'\'s,但不是同一个对象。

\n\n

另一件事,我们必须将toStringof (quote ...) 管理为 \'...

\n\n

与 LISP 相反的\'ss,`s 是 user/s!

\n\n

而对于宏管理,它做了很多改变...\xc2\xa0说\'s在执行命名空间,`s在编译命名空间,由读者执行。

\n