如何在 common-lisp CLOS 中指向 defgeneric 实例

How to point to a defgeneric instance in common-lisp CLOS

这里是 lisp 初学者。

我知道如何使用函数 find-method 指向特定的方法实例,并且我通过对返回的方法实例使用 slime inspect 看到它有一个插槽 %GENERIC- FUNCTION,但我无法使用它。

(为什么 (slot-value (find-method ...) '%GENERIC-FUNCTION) 告诉我对象中缺少插槽。

那么,我应该如何从 defmethod 对象指向 defgeneric 呢? 我正在使用 sbcl,但是是否有标准化的通用 lisp 方法来实现兼容性?

%GENERIC-FUNCTION 可能指的是您当前包中的符号,而不是内部包中标识插槽的符号。它们具有相同的名称,但属于不同的包。

你做的是CLOS的元对象协议(MOP)相关的,请参考metamodular.com/CLOS-MOP for more information (also, read AMOP)。

我们先加载 closer-mop:

USER> (ql:quickload :closer-mop)
To load "closer-mop":
  Load 1 ASDF system:
    closer-mop
; Loading "closer-mop"

(:CLOSER-MOP)

Closer-MOP系统是:

[...] a compatibility layer that rectifies many of the absent or incorrect CLOS MOP features across a broad range of Common Lisp implementations.

USER> (find-method #'print-object () (mapcar #'find-class '(vector t)))
#<STANDARD-METHOD COMMON-LISP:PRINT-OBJECT (VECTOR T) {10005605C3}>

(感谢 RainerJoswig 指出专家列表应该包含 class 对象而不是符号)

USER> (closer-mop:class-direct-slots (class-of *))
(#<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::%GENERIC-FUNCTION>
 #<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::QUALIFIERS>
 #<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::SPECIALIZERS>
 #<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::LAMBDA-LIST>
 #<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::%FUNCTION>
 #<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::%DOCUMENTATION>
 #<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::SIMPLE-NEXT-METHOD-CALL>)

确实,您需要使用 SB-PCL::%GENERIC-FUNCTION 符号:

USER> (slot-value ** 'SB-PCL::%GENERIC-FUNCTION)
#<STANDARD-GENERIC-FUNCTION COMMON-LISP:PRINT-OBJECT (277)>

(回想一下 *** 是表示在 REPL 中评估的最后一个和倒数第二个值的变量)

备注

这个插槽的SB-PCL::%GENERIC-FUNCTION符号没有导出(我们需要两个冒号来引用它),它以%字符开头,这是[=50=的约定]内部(有时危险)符号。你不应该直接使用它;也不推荐直接调用 slot-value,通常你只需要访问函数。

method-generic-function

相反,您应该使用从 closer-mop 导出的符号以获得更好的兼容性:

(closer-mop:method-generic-function 
  (find-method #'print-object () (mapcar #'find-class '(vector t))))