14

Lisp の内部を学びたいので、すべてがどのように実装されているかを知りたいです。

例えば、

(macroexpand '(loop for i upto 10 collect i))

私にくれます(SBCLで)

(BLOCK NIL
  (LET ((I 0))
    (DECLARE (TYPE (AND NUMBER REAL) I))
    (SB-LOOP::WITH-LOOP-LIST-COLLECTION-HEAD (#:LOOP-LIST-HEAD-1026
                                              #:LOOP-LIST-TAIL-1027)
      (SB-LOOP::LOOP-BODY NIL
                          (NIL NIL (WHEN (> I '10) (GO SB-LOOP::END-LOOP)) NIL)
                          ((SB-LOOP::LOOP-COLLECT-RPLACD
                            (#:LOOP-LIST-HEAD-1026 #:LOOP-LIST-TAIL-1027)
                            (LIST I)))
                          (NIL (SB-LOOP::LOOP-REALLY-DESETQ I (1+ I))
                           (WHEN (> I '10) (GO SB-LOOP::END-LOOP)) NIL)
                          ((RETURN-FROM NIL
                             (SB-LOOP::LOOP-COLLECT-ANSWER
                              #:LOOP-LIST-HEAD-1026)))))))

しかし、LOOP-BODY、WITH-LOOP-LIST-COLLECTION-HEAD などは依然としてマクロです。マクロ フォームを完全に展開するにはどうすればよいですか?

4

4 に答える 4

16

完全な展開を見るには、Lisp フォームをすべてのレベルで歩き、それらを展開する必要があります。このためには、このいわゆるコード ウォーカーが Lisp 構文を理解する必要があります (s 式の構文だけではありません)。たとえば、(lambda (a b) (setf a b))では、リスト(a b)はパラメータ リストであり、マクロ展開しないでください。

さまざまな Common Lisp 実装がそのようなツールを提供しています。MACROEXPAND-ALLSBCLが提供する6502件の回答の回答。

開発環境を使用する場合、通常はコマンドとして提供されます。

  • スライム:M-x slime-macroexpand-allありC-c M-m

  • LispWorks: menu Expression > Walk またはM-x Walk Form、短いM-Sh-m.

于 2013-05-16T06:22:17.727 に答える
11

他の回答はあなたの質問には優れていますが、すべてがどのように実装されているかを見たいと言っています。

多くのマクロ (既にご存じのとおり) はマクロを使用して実装されており、whilemacroexpand-allは非常に便利ですが、どのマクロがどの変更を担当したかというコンテキストを失う可能性があります。

(スライムを使用している場合) 良い妥協点の 1 つはslime-expand-1(Cc Enter) を使用することです。これは、拡張が別のバッファーであることを示します。次に、slime-expand-1この新しいバッファー内で使用して、マクロをその場で展開できます。これにより、読みながらツリーを展開しながら歩き、元に戻すを使用して展開を再び閉じることができます。

私にとって、これは他の人のマクロを理解する上で天からの贈り物でした。これがあなたにも役立つことを願っています、楽しんでください!

于 2013-05-16T12:40:09.480 に答える
3

使っMACROEXPAND-ALLてみることはできますが、得られるものは必ずしも有用ではありません。

本当の肉のようなものLOOPでは、生成されたコードではなく、マクロそのものです。

于 2013-05-16T05:56:29.007 に答える