如何将方法对象称为函数?
Closer-mop和clos包都提供了将方法对象转换为函数的方法函数。但是,有没有办法在不包含另一个包的情况下做到这一点?如果没有,哪个包?(使用 SBCL),但是如果需要一个包,那么鉴别功能是如何做到的呢?
这是使用 find-method 获取方法对象的示例。那么问题是如何调用method-to-be- call 。
(defclass a () ((x :accessor x :initform 0)))
(defgeneric inc (i))
(defmethod inc ((i a)) (incf (x i)))
(defvar r (make-instance 'a))
;; ... in a land far far away:
(defvar method-to-be-called (find-method #'inc '() '(a)))
(funcall method-to-be-called r);; crashes and burns
作为第二个问题,文档说鉴别功能首先尝试按类计算适用方法以查找方法对象,如果失败,则使用计算适用方法。为什么要采用这种两层方法?假设find-method正在执行这种两层方法是否正确,所以最好使用find-method?
-- 附录 -- 在下面的评论中,Rainer Joswig 指出这种查找方法形式是依赖于实现的:
(find-method #'inc '() '(a))) ; works on sbcl 1.3.1
他说说明符列表应该是类并建议:
(find-method #'inc '() (list (find-class 'a))))
所以我想把我的课放在那里:
(find-method #'inc '() (list a)) ; crashes and burns
显然(defclass a ... )没有将a设置为类。事实上,它并没有设置任何东西!
* (defclass a () ((x :accessor x :initform 0)))
#<STANDARD-CLASS COMMON-LISP-USER::A>
* a
... 变量 A 未绑定。
但是,这有效:
* (defvar ca (defclass a () ((x :accessor x :initform 0))))
CA
* (defmethod inc ((i a)) (incf (x i)))
WARNING: Implicitly creating new generic function COMMON-LISP-USER::INC.
#<STANDARD-METHOD COMMON-LISP-USER::INC (A) {1005EE8263}>
enter code here
* (find-method #'inc '() (list ca))
#<STANDARD-METHOD COMMON-LISP-USER::INC (A) {1005EE8263}>
*
所以类是 defclass 的返回值,而不是提供给 defclass 的符号的值。