Clojure 漂亮的打印嵌套语法引号

Clojure 漂亮的打印嵌套语法引号,clojure,quote,Clojure,Quote,是否有一种方法可以像在SBCL中那样以清晰的方式打印嵌套语法引号的计算结果?这在编写宏时调试嵌套语法引号时非常有用。例如,在Clojure 1.8中 (let [x '(1 2)] ``(~~@x)) 评估为 (clojure.core/seq (clojure.core/concat (clojure.core/list 1 2))) 在SBCL 1.3.6中,等效表达式 (let ((x '(1 2))) ``(,,@x)) 评估结果更清晰 `(,1 ,2) 表达式越复杂,差异越大。

是否有一种方法可以像在SBCL中那样以清晰的方式打印嵌套语法引号的计算结果?这在编写宏时调试嵌套语法引号时非常有用。例如,在Clojure 1.8中

(let [x '(1 2)] ``(~~@x))
评估为

(clojure.core/seq (clojure.core/concat (clojure.core/list 1 2)))
在SBCL 1.3.6中,等效表达式

(let ((x '(1 2))) ``(,,@x))
评估结果更清晰

`(,1 ,2)

表达式越复杂,差异越大。是否有任何Clojure软件包或其他方法可以帮助解决这种情况?目前,我发现调试复杂语法引号的最佳方法是将它们转换为通用Lisp,但这是一种相当荒谬且缓慢的方法。

如果您查看Clojure的LispReader类中的函数syntaxQuote(对象形式):

您将看到“(~@”(somelist))被理解为:

(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 ; it's the ref of the symbol ok
``s 
=> (quote user/s) ; it's the quoted ref 
```s
=> (clojure.core/seq ; now we manage a back-tick on a list
     (clojure.core/concat
       (clojure.core/list (quote quote)) 
       (clojure.core/list (quote user/s))))
````s
=> 
(clojure.core/seq ; oups! always a list we add a layer
 (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 ; same as ```s
            (clojure.core/concat
              (clojure.core/list (quote quote)) 
              (clojure.core/list (quote user/s))))
````~~s => (quote user/s) ; same as ``s
那么,你要说些什么呢

  • Clojure writer不会呈现reader宏接收到的引号 因此它给出了
    (引号s)
    ,而不是
    。这是针对数组、集合、
  • back tick宏读取器不会简化列表/报价匹配。仅引用列表和单个条目的串联应立即执行,并给出

    ````~~s=>s

  • 如果您管理列表、数组或集合上的倒勾,问题会更严重……;) 问题是“不是”

    如果我记得在LISP中,作为结果给出的是

    可以这样查看管理简化版本的可能性

    (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))
    
    结果相当于
    ”的
    ,但它不是同一个对象

    另一件事,我们必须将(quote…)的
    toString
    管理为“

    与LISP相反,
    s
    ,`s是用户


    对于宏管理,它进行了很多更改…例如,s在执行命名空间中,`s在编译命名空间中,由读取器执行。

    我假设您的意思是
    `(一些列表)
    ,而不是
    `(一些列表)
    。这可以计算为
    `(clojure.core/some clojure.core/list)
    。符号解析不是问题,因为符号是完全限定的。@Qudit我修改了响应以更准确地理解问题。Clojure确实从嵌套的语法引号生成了非常难看的代码,但没有根本原因(或一个漂亮的打印语法引号包)不能再像SBCL那样做了。语法引号只需要扩展到以某种方式运行的代码。Clojure为此目的生成的特定代码没有什么特别之处。我添加了som补充内容,因为在注释中格式不可读。我希望我没有错过解释,可能会有点混乱。这就是为什么宏观管理会导致不明显的问题。backtick是一个reader宏,所以转换是在读取时完成的,编译后的宏已经有了转换的内容,如果有多个嵌套级别,这可能会让人混淆。引用不存在。。。它只是一个值,引用是给程序员的,程序就是这个值。
    (seq '(clojure.core/seq 'user/s))