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-all有C-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再次关闭扩展.
对我来说,这是了解其他人的宏的神.希望这对你有所帮助,玩得开心!