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

Posted

技术标签:

【中文标题】如何在 common-lisp CLOS 中指向一个 defgeneric 实例【英文标题】:How to point to a defgeneric instance in common-lisp CLOS 【发布时间】:2020-01-25 09:46:28 【问题描述】:

这里是lisp初学者。

我知道如何使用函数 find-method 指向特定的方法实例,我从使用 slime 检查返回的方法实例中看到它有一个插槽 %GENERIC-FUNCTION,但我不能使用它。

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

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

【问题讨论】:

【参考方案1】:

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

您所做的与 CLOS 的元对象协议 (MOP) 有关,请参阅metamodular.com/CLOS-MOP 了解更多信息(另请阅读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 系统是:

[...] 一个兼容层,可以纠正许多缺失或 广泛的 Common Lisp 中不正确的 CLOS MOP 功能 实现。

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

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

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 符号未导出(我们需要两个冒号来引用它),它以% 字符开头,这是internal 的约定(有时危险)符号。你不应该直接使用它;也不推荐直接调用slot-value,一般只需要accessor函数即可。

method-generic-function

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

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

【讨论】:

(find-method #'print-object () (list 'vector t)) 不可移植。您需要传递一个类对象列表。请参阅 CLHS 7.6.2:参数专用器名称用于宏中,用作用户级接口(defmethod),而参数专用器用于功能接口。

以上是关于如何在 common-lisp CLOS 中指向一个 defgeneric 实例的主要内容,如果未能解决你的问题,请参考以下文章

Common-Lisp:绑定形式参数,到底传递了啥?

使用粘贴时如何跳转到emacs中的函数定义?

CLOS架构是啥?

CLOS:如何使插槽具有强制类型的符号向量?

关于CLOS架构的举例 网络级 设备级 FATTREE网络 网络级CLOS 以及CLOS涉及的调度算法RR

当该行的 clos 与上一行具有重复值时,如何进行 sql Select 查询,以便在后续行中将某些列留空?