如何重写这个 Common Lisp 宏来避免反引号?

How to re-write this Common Lisp macro avoiding the back-quote notation?

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

在上一章的宏中,作者给出了重写内置incf宏的例子。他用两种不同的方法教授这个概念:使用反引号和不使用反引号。如:

(defmacro list-notation-my-incf (x)
  (list 'setq x (list '+ x 1)))

(defmacro backquote-notation-my-incf (x)
  `(setq ,x (+ ,x 1)))

后面作者再介绍一个例子:

In the example below, TWO-FROM-ONE is a macro that takes a function name and another object as arguments; it expands into a call to the function with two arguments, both of which are the quoted object.

他只用反引号来做:


(defmacro two-from-one (func object)
  `(,func ',object ',object))

它按预期工作:

CL-USER> (two-from-one cons stack-overflow)
(STACK-OVERFLOW . STACK-OVERFLOW)

使用 slime-macroexpad-1,我有:

(CONS 'STACK-OVERFLOW 'STACK-OVERFLOW)

作为我为自己创建的练习,我尝试做同样的事情,但避免了反引号。不幸的是,我无法让它工作:

(defmacro list-two-from-one (func object)
  (list func (quote object) (quote object)))

Slime 抛出错误:

The variable OBJECT is unbound.
   [Condition of type UNBOUND-VARIABLE]

做一个宏展开,我看到:

(CONS OBJECT OBJECT)

如果我尝试不同的方法,它似乎更接近,但它也不起作用:

(defmacro list-two-from-one (func object)
  (list func object object))

抛出错误:

The variable STACK-OVERFLOW is unbound.
   [Condition of type UNBOUND-VARIABLE]

最后,宏扩展表示:

(CONS STACK-OVERFLOW STACK-OVERFLOW)

我觉得卡住了。如何在不使用反引号的情况下成功重写宏?

谢谢。

您的宏应扩展为:

CL-USER 10 > (macroexpand '(two-from-one2 cons stack-overflow))
(CONS (QUOTE STACK-OVERFLOW) (QUOTE STACK-OVERFLOW))

所以用 quote 创建列表,如下所示:

(defmacro two-from-one2 (func object)
  (list func (list 'quote object) (list 'quote object)))

测试:

CL-USER 9 > (two-from-one2 cons stack-overflow)
(STACK-OVERFLOW . STACK-OVERFLOW)

你要找的是

(defmacro list-two-from-one (func object)
  (list func (list 'quote object) (list 'quote object)))

基本上,宏的主体应该 return 代码,在评估时 会产生所需的结果。

即宏体应该产生 (CONS 'STACK-OVERFLOW 'STACK-OVERFLOW).

由于 'a(quote a) 相同,您希望宏生成

(CONS (QUOTE STACK-OVERFLOW) (QUOTE STACK-OVERFLOW))

这就是我上面的 defmacro returns.