完全展开宏窗体

Mik*_*one 12 lisp macros common-lisp

我想学习Lisp的内部,所以我想看看一切是如何实现的.

例如,

(macroexpand '(loop for i upto 10 collect i))
Run Code Online (Sandbox Code Playgroud)

给了我(在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)))))))
Run Code Online (Sandbox Code Playgroud)

但是LOOP-BODY,WITH-LOOP-LIST-COLLECTION-HEAD等仍然是宏.如何完全展开宏窗体?

Rai*_*wig 15

要查看完整的扩展,需要在所有级别上遍历Lisp表单并展开它们.为此,这个所谓的代码遍历器必须理解Lisp语法(而不仅仅是s表达式语法).例如(lambda (a b) (setf a b)),列表(a b)是参数列表,不应进行宏扩展.

各种Common Lisp实现提供了这样的工具.MACROEXPAND-ALL由SBCL提供的6502提到的答案.

如果您使用开发环境,它通常作为命令提供:

  • SLIME:M-x slime-macroexpand-allC-c M-m

  • LispWorks:菜单 > 步行M-x Walk Form较短M-Sh-m.


Bag*_*ers 10

其他答案对你来说非常好,但你说你想看看一切是如何实现的.

许多宏(如您所知)已经使用宏实现,虽然macroexpand-all非常有用,但您可能会失去宏负责什么变化的上下文.

一个不错的中间地带(如果你使用粘液)是使用slime-expand-1(Cc Enter),它显示扩展是另一个缓冲区.然后,您可以slime-expand-1在此新缓冲区内使用以就地扩展宏.这允许您在阅读时遍历树扩展,并使用undo再次关闭扩展.

对我来说,这是了解其他人的宏的神.希望这对你有所帮助,玩得开心!