methods - 如何使用标准函数调用方法对象

标签 methods common-lisp clos ansi-common-lisp

如何将方法对象作为函数来调用?

Closer-mopclos 包都提供method-function 用于将方法对象转换为函数。但是,有没有办法在不包含另一个包的情况下做到这一点?如果不是,哪个包? (使用SBCL),但如果需要一个包,那么判别函数是怎么做的呢?

这里是一个使用find-method获取方法对象的例子。接下来的问题是如何调用要调用的方法

(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

作为次要问题,文档说辨别函数首先尝试compute-applicable-methods-by-class 来找到方法对象,如果失败,它使用计算适用方法。为什么采用这种两层方法?假设 find-method 正在执行这种两层方法是否正确,因此最好使用 find-method

-- 附录 -- 在下面的评论中,Rainer Joswig 指出这种查找方法形式依赖于实现:

(find-method #'inc '() '(a))) ; works on sbcl 1.3.1

他说说明符列表应该是类并建议改为:

(find-method #'inc '() (list (find-class 'a))))

所以我想把我的类(class)放在那里:

(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 未绑定(bind)。

但是,这是可行的:

* (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 的符号的值。

最佳答案

(find-method #'inc '() '(a))

以上无效。我们需要一个类列表,而不是符号列表。

(funcall (method-function (find-method #'inc
                                       '()
                                       (list (find-class 'a))))
         r)

由于函数 method-function 属于 MOP,许多实现都提供它,并且它在一些实现特定的包中。 CLOSER-MOP 也使其可用。

但通常情况下,如果您已经在尝试提取方法函数,那么您可能以错误的方式使用 CLOS,或者您真的知道自己在做什么...

关于methods - 如何使用标准函数调用方法对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35220471/

相关文章:

class - 有没有办法获得类(class)的名额?

C# 参数化方法数组或参数化方法列表

methods - .aidl 文件中的方法是否有 "@Deprecated"注释?

lisp - 如何修改这个 "make-matrix"函数?

Lisp Def 方法结构

php - 类似于 CLOS 的 PHP 对象模型

ruby-on-rails - 愚蠢的 block 中的 block rspec 测试

Java 数独解决方案 validator

lisp - 使用# a.k.a. 读取宏

io - 用 lisp 将列表写入文件