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-classallows 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-classesallows 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 witheqlspecializers.I am speculating here, but it makes sense to fall back on
compute-applicable-methodsto 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-classesgeneric function specified anywhere.