lis*_*ons 4 lisp macros common-lisp
这可能是一个愚蠢的问题,但我正在浏览 PG lisp 书,我想逐步了解他提供的一些带有实际值的示例宏,例如:
(defmacro our-let (binds &body body)
`(
(lambda ,(
mapcar #'(lambda (x) (if (consp x) (car x) x)) binds
)
,@body
)
,@(mapcar #'(lambda (x) (if (consp x) (cadr x) nil)) binds)
)
)
Run Code Online (Sandbox Code Playgroud)
我天真地尝试运行(trace our-let)
,然后(our-let ((x 1) (y 2)) (+ x y))
我收到一个错误,can't use encapsulation to trace anonymous function #<FUNCTION (MACRO-FUNCTION OUR-LET) {22675BBB}>
. 也不确定如何最好地将print
语句放入 lambda 表达式中。调试此宏/输出如何处理输入的最佳方法是什么?
编辑(1):我的 格式不正确macroexpand
,但有效。
实际上,能够跟踪宏在 Common Lisp 实现中并不常见。编译器通常会在编译期间扩展宏表单。
一些实现虽然支持它 - 当它们还支持运行实际源代码的 Lisp 解释器时,这是有道理的。其中包括 LispWorks 和 CLISP。
这里使用 CLISP 中来自 Sylwester 的代码:
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ `+' / I 8 8 8 8 8 8
\ `-+-' / 8 8 8 ooooo 8oooo
`-__|__-' 8 8 8 8 8
| 8 o 8 8 o 8 8
------+------ ooooo 8oooooo ooo8ooo ooooo 8
Welcome to GNU CLISP 2.49.93+ (2018-02-18) <http://clisp.org/>
Copyright (c) Bruno Haible, Michael Stoll 1992-1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2018
Type :h and hit Enter for context help.
[1]> (defmacro our-let ((&rest bindings) &body body)
(let ((names (mapcar #'(lambda (x) (if (consp x) (car x) x)) bindings))
(exprs (mapcar #'(lambda (x) (if (consp x) (cadr x) nil)) bindings)))
`((lambda ,names ,@body) ,@exprs)))
OUR-LET
[2]> (trace our-let)
;; Tracing macro OUR-LET.
(OUR-LET)
[3]> (dotimes (i 3)
(our-let ((x (* i 10)))
(+ x 3)))
1. Trace: (OUR-LET ((X (* I 10))) (+ X 3))
1. Trace: OUR-LET ==> ((LAMBDA (X) (+ X 3)) (* I 10))
1. Trace: (OUR-LET ((X (* I 10))) (+ X 3))
1. Trace: OUR-LET ==> ((LAMBDA (X) (+ X 3)) (* I 10))
1. Trace: (OUR-LET ((X (* I 10))) (+ X 3))
1. Trace: OUR-LET ==> ((LAMBDA (X) (+ X 3)) (* I 10))
NIL
[4]>
Run Code Online (Sandbox Code Playgroud)