How does one call a method object as a function?
Closer-mop and clos packages both provide method-function for turning a method object into a function. However, is there a way to do it without including another package? And if not, which package? (Using SBCL), but if a package is needed then how does the discrimination function do it?
Here is an example of using find-method to get a method object. The question is then how to call method-to-be-called.
(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
As a secondary question, the docs say that the discrimination function first tries to compute-applicable-methods-by-class to find a method object, and if that fails, it uses compute-applicable-methods. Why do this two layer approach? Is it correct to assume the find-method is doing this two layer approach, so it is better to use find-method ?
-- Appendix -- In the comments below Rainer Joswig pointed out that this find-method form is implementation dependent:
(find-method #'inc '() '(a))) ; works on sbcl 1.3.1
He says the specifier list should be classes and suggests instead:
(find-method #'inc '() (list (find-class 'a))))
So I thought to just put my class in there:
(find-method #'inc '() (list a)) ; crashes and burns
Apparently (defclass a ... ) does not set a to a class. In fact it doesn't set it to anything!
* (defclass a () ((x :accessor x :initform 0)))
#<STANDARD-CLASS COMMON-LISP-USER::A>
* a
... The variable A is unbound.
However, this works:
* (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}>
*
So a class is the return value from the defclass, not the value of the symbol that is provided to defclass.
For the particular case of
method-function
, closer-mop for SBCL simply reexport the existing symbol fromsb-pcl
, as seen in closer-mop-packages.lisp. The whole file make use of read-time conditionals (see 1.5.2.1 Use of Implementation-Defined Language Features). That means that if you are working with SBCL, you might callsb-pcl:method-function
(PCL means Portable Common Loops).The generic function
compute-applicable-methods-by-class
allows you to know which methods are applicable given classes. This is useful if you don't have actual instances on which you can operate. It seems also thatcompute-applicable-methods-using-classes
allows the implementation to memoize the applicable methods when the second return value istrue
. This generic method does not allow you to find applicable methods specialized witheql
specializers.I am speculating here, but it makes sense to fall back on
compute-applicable-methods
to allow for exampleeql
-specializers or because it is slightly easier to define a method forcompute-applicable-methods
. Note the paragraph about consistency:I don't think there is a
find-method-using-classes
generic function specified anywhere.