2016-11-26 48 views
4

有沒有一種方法可以像在SBCL中一樣以可讀的方式打印評估嵌套語法引號的結果?在編寫宏時調試嵌套的語法引用時,這會很有用。例如,在1.8的Clojure,漂亮的打印嵌套語法引號

(let [x '(1 2)] ``([email protected])) 

評估爲

(clojure.core/seq (clojure.core/concat (clojure.core/list 1 2))) 

在SBCL 1.3.6,等效表達

(let ((x '(1 2))) ``(,,@x)) 

計算結果爲更清晰

`(,1 ,2) 

區別b隨着更復雜的表情而變得更大。有沒有Clojure包或其他方法可以幫助解決這種情況?目前,我發現調試複雜語法引用的最佳方式是將它們轉換爲Common Lisp,但這是一種相當荒謬和緩慢的方法。

回答

1

如果你看看Clojure中的LispReader類的功能syntaxQuote(對象形式): 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) 

剛看看`

`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的作家被原樣不渲染報價閱讀器宏 所以它給出(quote s)而不是's。這是爲陣列,集合,...
  2. 回撥宏讀取器不會簡化列表/報價匹配。應該立即執行僅引用列表和單個條目的連接,給出

    ```~~ s =>'s。

  3. 如果你設法回到滴答作響的列表或數組或集合...問題更是雪上加霜;)

的問題是,'s不是的。

如果我記得LISP給出的結果。)

來管理的簡化版本一種可能性可以被看作這樣

(clojure.core/seq 
    (clojure.core/concat 
    (clojure.core/list (quote quote)) 
    (clojure.core/list (quote user/s)))) 

可以在宏代地改變

(seq 'user/s) 

但是!!!結果是一個序列,比如一個懶惰的序列,而不是'user/s

讓我們嘗試一下````。簡化會給:

(seq '(clojure.core/seq 'user/s)) 

結果相當於''s,但它不是同一個對象。

另一件事情,我們要管理的toString(報價...)爲」 ......

出乎LISP 'ss和's是用戶/秒!

對於宏管理,它做了很多改變......說的是在執行命名空間中,是在編譯命名空間中,由讀者執行。

+0

我假定你的意思是''''(某些列表)''而不是''(某些列表)''。這可以評估爲'\'(clojure.core /某些clojure.core/list)'。符號分辨率不是問題,因爲符號是完全合格的。 – Qudit

+0

@Qudit我修改了回答,以更準確地掌握問題。 –

+0

Clojure從嵌套的語法引用中生成非常醜陋的代碼當然是事實,但是爲什麼它(或者一個漂亮的打印語法引用包)不能做更像SBCL發生的事情那樣的根本原因。語法引號只需要展開到以某種方式運行的代碼即可。 Clojure爲此目的生成的特定代碼沒有什麼特別之處。 – Qudit