lisp beginner here.
I get how to point to a specific method instance using function find-method and I see from using slime inspect on the returned method instance that it has a slot %GENERIC-FUNCTION, but I cannot use it.
(why does (slot-value (find-method ...) '%GENERIC-FUNCTION)
tells me that the slot is missing from the object.
So, how should I do to point to a defgeneric from a defmethod object ? I'm using a sbcl, but is there a standardized common-lisp way to do it for compatibility ?
%GENERIC-FUNCTION
probably refers to a symbol in your current package, and not the symbol in the internal package that identifies the slot. They have the same name, but belong to different packages.
What you are doing is related to the Meta-Object Protocol (MOP) of CLOS, please refer to metamodular.com/CLOS-MOP for more information (also, read AMOP).
Let's first load closer-mop
:
USER> (ql:quickload :closer-mop)
To load "closer-mop":
Load 1 ASDF system:
closer-mop
; Loading "closer-mop"
(:CLOSER-MOP)
The Closer-MOP system is:
[...] a compatibility layer that rectifies many of the absent or incorrect CLOS MOP features across a broad range of Common Lisp implementations.
USER> (find-method #'print-object () (mapcar #'find-class '(vector t)))
#<STANDARD-METHOD COMMON-LISP:PRINT-OBJECT (VECTOR T) {10005605C3}>
(Thanks to RainerJoswig for pointing out that the list of specializers should contain class objects and not symbols)
USER> (closer-mop:class-direct-slots (class-of *))
(#<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::%GENERIC-FUNCTION>
#<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::QUALIFIERS>
#<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::SPECIALIZERS>
#<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::LAMBDA-LIST>
#<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::%FUNCTION>
#<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::%DOCUMENTATION>
#<SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION SB-PCL::SIMPLE-NEXT-METHOD-CALL>)
So indeed, you need to use the SB-PCL::%GENERIC-FUNCTION
symbol:
USER> (slot-value ** 'SB-PCL::%GENERIC-FUNCTION)
#<STANDARD-GENERIC-FUNCTION COMMON-LISP:PRINT-OBJECT (277)>
(recall that *
and **
are variables that represent the last and second to last values evaluated in a REPL)
The SB-PCL::%GENERIC-FUNCTION
symbol for this slot is not exported (we need two colons to refer to it), and it starts with a %
character, which is a convention for internal (sometimes dangerous) symbols. You should not use it directly; also calling slot-value
directly is not recommanded, usually you only need accessor functions.
method-generic-function
Instead, you should use the symbols exported from closer-mop
for better compatibility:
(closer-mop:method-generic-function
(find-method #'print-object () (mapcar #'find-class '(vector t))))