我编写了以下代码作为 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)))
,@)))
编译器会抱怨在反引号之外使用逗号。
我猜错误的原因是读取器宏函数应该以某种方式与反引号语法配合,但我无法找到一种方法来做到这一点。有什么建议吗?
谢谢!
在评论中指出这是不可能可移植的,这就是为什么它实际上必须是可能的:如果不是,则在不依赖于特定于实现的特殊魔法的情况下不可能为
#\(
编写一个读取宏.
然而,在实现这样的 readmacros 时,您需要做的一件事是告诉读者您正在递归读取。这使得
#
n=
/ #
n#
之类的东西可以工作,但看起来它也可能让读者知道它可能期望看到一个没有 LispWorks 周围反引号的逗号。这可能是作为健全性检查而完成的,尽管我不能代表 LW 实现者说话。
为此,您必须确保将
read
称为“(read s t nil t)”(或者无论如何确保第四个参数为 true)。