为啥这个在 Common Lisp 中漂亮地打印宏扩展的宏不起作用?都有哪些替代工具?

Posted

技术标签:

【中文标题】为啥这个在 Common Lisp 中漂亮地打印宏扩展的宏不起作用?都有哪些替代工具?【英文标题】:Why this macro to pretty print macro expansions in Common Lisp does not work? What are the alternatives tools for this?为什么这个在 Common Lisp 中漂亮地打印宏扩展的宏不起作用?有哪些替代工具? 【发布时间】:2021-10-20 16:31:50 【问题描述】:

我正在尝试通过Common Lisp:符号计算的简单介绍这本书来学习 Common Lisp。此外,我正在使用 SBCL、Emacs 和 Slime。

在第 14 章,最后一章,作者介绍了。他提出了一个名为PPMX 的工具,代表:“Pretty Print Macro eXpansion”。

使用此工具,您可以:

> (ppmx (incf a))
Macro expansion:
(SETQ A (+ A 1))

该工具是独立的,因为本书为其提供了代码定义:

(defmacro ppmx (form)
  "Pretty prints the macro expansion of FORM."
  ‘(let* ((exp1 (macroexpand-1 ’,form))
          (exp (macroexpand exp1))
          (*print-circle* nil))
     (cond ((equal exp exp1)
            (format t "~&Macro expansion:")
            (pprint exp))
           (t (format t "~&First step of expansion:")
              (pprint exp1)
              (format t "~%~%Final expansion:")
              (pprint exp)))
     (format t "~%~%")
     (values)))

不幸的是,我无法运行它,因为编译不起作用。 Slime 的 REPL 会抛出这个错误:

ch-14.lisp:3:33:
  read-error: 
    READ error during COMPILE-FILE:
    
      Comma not inside a backquote.
    
        Line: 3, Column: 33, File-Position: 101
    
        Stream: #<SB-INT:FORM-TRACKING-STREAM for "file /tmp/slimeD4xBr3" 10036BFC63>

Compilation failed.

emacs 中的逗号和左单引号看起来与 SO 中的不同:

我在将代码从书中复制到 emacs 时遇到了一些问题。它基本上是插入' 而不是左单引号。

1 - 有没有办法解决这个问题?

2 - 这本书写于 1980 年代后期。因此,我敢打赌现在有更好的工具。 Slime 或 SBCL 是否提供一些命令来漂亮地打印宏扩展?也许是一个库或其他包?

谢谢。

【问题讨论】:

您使用的是弯引号 ,而不是 ASCII 反引号 ` 谢谢!但是,即使解决了这个问题,REPL 仍然指出:The variable FORM is unbound. [Condition of type UNBOUND-VARIABLE] 这里还有一个弯引号:’,form。那应该是一个 ASCII 单引号 ' 在编辑代码时使用编程编辑器或关闭“智能引号”。 如果你只是在(macroexpand '(...)) 之前执行(setq *print-pretty* t),它会在REPL 中漂亮地打印出来。 【参考方案1】:

按照@barmar 的建议,用户只需要在REPL 中写:

CL-USER> *print-pretty*
T
CL-USER> (macroexpand (setf a 1))  ;without the quote it does not work
1
NIL
CL-USER> (macroexpand '(setf a 1)) ;with the quote it does
(SETQ A 1)
T

【讨论】:

以上是关于为啥这个在 Common Lisp 中漂亮地打印宏扩展的宏不起作用?都有哪些替代工具?的主要内容,如果未能解决你的问题,请参考以下文章

Common Lisp宏变量扩展

Common Lisp:将符号传递给宏

为啥这个 Common Lisp 宏不起作用?书上的答题卡错了吗?

将 Common Lisp 中的宏参数视为(区分大小写的)字符串

为啥 Common Lisp 在没有引号的情况下评估符号本身?

在 common lisp 中居中文本