2016-11-26 3 views
4

SBCLのように、ネストされたシンタックス引用符の評価結果を目に見える形で印刷する方法はありますか?これは、マクロの作成時にネストされた構文引用符をデバッグするときに便利です。例えば、Clojureの1.8に入れ子になったシンタックスの引用符の印刷

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

は、SBCL 1.3.6で

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

(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))); 

をあなたはとして読み取られる `(〜@ '(一部リスト))ことがわかりますただ、

=> (some list) 

:としてREPLによって評価される

(clojure.core/seq 
    (clojure.core/concat 
    (clojure.core/list (quote clojure.core/some)) 
    (clojure.core/list (quote clojure.core/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のライターは、引用符をレンダリングしないようにする発言は何ですかリーダーマクロ ですので、'sの代わりに(quote s)となります。
  2. バックティックマクロリーダーは、リストとクォートのマッチングを単純化しません。引用されたリストと単一エントリの連結は、すぐに実行されなければなりません。

    `` `` ~~ s => ''

  3. 問題は、あなたが管理している場合...リストや配列やセットにバック刻々と過ぎさらに悪くなる;)

問題は `s「はsのではないということです。

私がLISPで覚えているのは、結果として与えるものです。;)

簡略化されたバージョンを管理する可能性が

(seq 'user/s) 

しかしとして

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

マクロ世代で変更することができるように見ることができます!その結果は、'user/sではなく、レイジーシーケンスなどのシーケンスです。

`` ``を試してみましょう。簡略化すると次のようになります。

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

結果は''sと同じですが、同じオブジェクトではありません。

もう一つ、私たちは...(引用...)「などのtoStringを管理するために

を持っており、'ssあるとLispに反し `sがユーザー/ sであります!

マクロ管理のために、それは多くの変更を行います...実行ネームスペースにあり、 `sはコンパイル名前空間にあり、読者によって実行されます。

+0

私はあなたが '\'(いくつかのリスト) 'の代わりに' \ '\'(いくつかのリスト) 'を使用したと仮定します。これは '\'(clojure.core/some clojure.core/list) 'に評価されます。シンボルが完全修飾されているため、シンボルの解像度は問題にはなりません。 – Qudit

+0

@ Qudit問題をより正確に把握するためにレスポンスを修正しました。 –

+0

もちろん、Clojureはネストされた構文引用符から非常に醜いコードを生成しますが、SBCLの場合のように何かを行うことができない根本的な理由はありません。構文引用符は、特定の方法で動作するコードに展開するだけです。 Clojureがこの目的のために生成する特定のコードについて特別なものは何もありません。 – Qudit

関連する問題