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

Methods 如何使用标准函数调用方法对象,methods,common-lisp,clos,ansi-common-lisp,Methods,Common Lisp,Clos,Ansi Common Lisp,如何将方法对象作为函数调用 Closer mop和clos包都提供了方法函数,用于将方法对象转换为函数。然而,有没有一种方法可以在不包含另一个包的情况下做到这一点?如果没有,是哪一个包裹?(使用SBCL),但如果需要一个包,那么辨别功能是如何实现的 下面是一个使用find方法获取method对象的示例。然后问题是如何调用要调用的方法 (defclass a () ((x :accessor x :initform 0))) (defgeneric inc (i)) (defmethod inc

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

Closer mopclos包都提供了方法函数,用于将方法对象转换为函数。然而,有没有一种方法可以在不包含另一个包的情况下做到这一点?如果没有,是哪一个包裹?(使用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
作为第二个问题,文档说判别函数首先尝试按类计算适用方法,以找到方法对象,如果失败,则使用计算适用方法。为什么要采用这种两层方法?假设查找方法正在执行此两层方法是否正确,因此最好使用查找方法

--附录-- 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
*(defclass a()((x:accessor x:initform 0)))
#
*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}>
* 
*(defvar ca(defclass a()((x:accessor x:initform 0)))
加利福尼亚州
*(defmethod inc((i a))(incf(x i)))
警告:隐式创建新的通用函数COMMON-LISP-USER::INC。
#
在这里输入代码
*(查找方法#'inc'()(列表ca))
#
* 

因此,类是defclass的返回值,而不是提供给defclass的符号的值。

对于
方法函数的特定情况,SBCL的closer mop只需从
sb pcl
重新导出现有符号,如中所示。整个文件使用读取时间条件(请参阅)。 这意味着,如果您使用SBCL,您可以调用
sb pcl:method function
(pcl表示可移植的公共循环)

通用函数
按类计算适用的方法
允许您知道在给定的类中哪些方法是适用的。如果您没有可以操作的实际实例,这将非常有用。
另外,似乎
使用类计算适用的方法
允许实现在第二个返回值为
true
时记忆适用的方法。此泛型方法不允许您查找使用
eql
专门化器专门化的适用方法

我在这里猜测,但有必要求助于
计算适用方法
,以允许例如
eql
-专门化器,或者因为为
计算适用方法
定义方法稍微容易一些。 请注意关于一致性的问题:

必须保持使用类的计算适用方法和计算适用方法之间的以下一致性关系:对于任何给定的泛型函数和参数集,如果使用类的计算适用方法返回第二个值true,第一个值必须等于计算适用方法的相应调用将返回的值。如果这些泛型函数中的任何一个上的可移植方法导致违反此一致性,则结果是未定义的


我认为没有一个
查找方法使用任何地方指定的类
泛型函数。

对于
方法函数
的特殊情况,SBCL的closer mop只需从
sb pcl
重新导出现有符号,如中所示。整个文件使用读取时间条件(请参阅)。
(find-method #'inc '() '(a))
这意味着,如果您使用SBCL,您可以调用
sb pcl:method function
(pcl表示可移植的公共循环)

通用函数
按类计算适用的方法
允许您知道在给定的类中哪些方法是适用的。如果您没有可以操作的实际实例,这将非常有用。
另外,似乎
使用类计算适用的方法
允许实现在第二个返回值为
true
时记忆适用的方法。此泛型方法不允许您查找使用
eql
专门化器专门化的适用方法

我在这里猜测,但有必要求助于
计算适用方法
,以允许例如
eql
-专门化器,或者因为为
计算适用方法
定义方法稍微容易一些。 请注意关于一致性的问题:

必须保持使用类的计算适用方法和计算适用方法之间的以下一致性关系:对于任何给定的泛型函数和参数集,如果使用类的计算适用方法返回第二个值true,第一个值必须等于计算适用方法的相应调用将返回的值。如果这些泛型函数中的任何一个上的可移植方法导致违反此一致性,则结果是未定义的

我认为没有一个
查找方法使用任何地方指定的类
泛型函数

(find-method #'inc '() '(a))
上述方法不起作用。我们需要类的列表,而不是符号的列表

(funcall (method-function (find-method #'inc
                                       '()
                                       (list (find-class 'a))))
         r)
由于函数<代码>方法函数属于MOP,因此许多实现都提供了它,并且它在一些特定于实现的包中<代码>CLOSER-MOP
也可以使用

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

上述方法不起作用。我们需要类的列表,而不是符号的列表

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