在宏定义中使用读取器宏字符

问题描述 投票:0回答:1

我编写了以下代码作为 LispWorks COM 包的瘦包装器的一部分,以便使访问 COM 对象中的属性看起来更像 s 表达式:

;;; Create dispatch function for '#<' and '#>'.
(eval-when (:load-toplevel :compile-toplevel :execute)
  (defun com-dispatch-function (invoke-function)
    (lambda (stream sub-char infix)
      (declare (ignore sub-char infix))
      (destructuring-bind (thing object &rest args)
          (read stream)
        `(,invoke-function ,object (symbol-name ',thing) ,@args)))))


;;; COM 'get property' read macro.
(set-dispatch-macro-character
 #\# #\<
 (com-dispatch-function 'com::invoke-dispatch-get-property))

所以现在,而不是

(invoke-dispatch-get-property object "Property" argument)

我会写

#<(property object argument)

但是,当我尝试在宏定义中使用此语法时,如下所示:

(defmacro something ((object) &body body)
  (let ((excel (gensym)))
    `(cclet* ((,excel #<(application ,object)))
      ,@))) 

编译器会抱怨在反引号之外使用逗号。

我猜错误的原因是读取器宏函数应该以某种方式与反引号语法配合,但我无法找到一种方法来做到这一点。有什么建议吗?

谢谢!

common-lisp reader-macro
1个回答
0
投票

在评论中指出这是不可能可移植的,这就是为什么它实际上必须是可能的:如果不是,则在不依赖于特定于实现的特殊魔法的情况下不可能为

#\(
编写一个读取宏.

然而,在实现这样的 readmacros 时,您需要做的一件事是告诉读者您正在递归读取。这使得

#
n
=
/
#
n
#
之类的东西可以工作,但看起来它也可能让读者知道它可能期望看到一个没有 LispWorks 周围反引号的逗号。这可能是作为健全性检查而完成的,尽管我不能代表 LW 实现者说话。

为此,您必须确保将

read
称为“(read s t nil t)”(或者无论如何确保第四个参数为 true)。

© www.soinside.com 2019 - 2024. All rights reserved.