漂亮的打印嵌套语法引号

时间:2016-11-26 22:09:31

标签: 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)

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

1 个答案:

答案 0 :(得分:1)

如果你在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)));

你会看到`(〜@'(某些列表))被读作:

(clojure.core/seq
  (clojure.core/concat
    (clojure.core/list (quote clojure.core/some))
    (clojure.core/list (quote clojure.core/list))))

由REPL评估为:

=> (some list)

看看`alone

的效果
`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

那么要做什么呢?

  1. Clojure writer不会呈现读者宏所接收的引号 所以它提供(quote s)而不是's。这是针对数组,set,...
  2. 完成的
  3. back-tick宏读取器不会对列表/引用匹配进行简化。应该立即执行仅引用列表和单个条目的连接,给出

    ````~~ s => '' S

  4. 如果您在列表或数组或集合上管理反向滴答,问题会更严重......;)
  5. 问题在于,不是。

    如果我记得在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))
    

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

    另外,我们必须将toString(引用...)作为'...

    进行管理

    与LISP相反'ss而且`s是user / s !!!

    对于宏管理,它进行了很多更改...... Say在执行命名空间中,`s在编译命名空间中,由读者执行。