Как указать на экземпляр defgeneric в common-lisp CLOS

новичок в lisp здесь.

Я понимаю, как указать на конкретный экземпляр метода с помощью функции find-method, и я вижу, используя слизь для проверки возвращаемого экземпляра метода, что у него есть слот %GENERIC-FUNCTION, но я не могу его использовать.

(почему (slot-value (find-method ...) '%GENERIC-FUNCTION) говорит мне, что в объекте отсутствует слот.

Итак, как мне сделать, чтобы указать на defgeneric из объекта defmethod? Я использую sbcl, но есть ли стандартизированный способ Common-Lisp сделать это для совместимости?


person VinD    schedule 25.09.2019    source источник


Ответы (1)


%GENERIC-FUNCTION, вероятно, относится к символу в вашем текущем пакете, а не к символу во внутреннем пакете, который идентифицирует слот. Они имеют одинаковое имя, но относятся к разным пакетам.

То, что вы делаете, связано с протоколом метаобъектов (MOP) CLOS, см. metamodular.com/CLOS-MOP для получения дополнительной информации (также прочитайте AMOP ).

Давайте сначала загрузим closer-mop:

USER> (ql:quickload :closer-mop)
To load "closer-mop":
  Load 1 ASDF system:
    closer-mop
; Loading "closer-mop"

(:CLOSER-MOP)

Система Closer-MOP:

[...] уровень совместимости, исправляющий многие из отсутствующих или неправильных функций CLOS MOP в широком диапазоне реализаций Common Lisp.

USER> (find-method #'print-object () (mapcar #'find-class '(vector t)))
#<STANDARD-METHOD COMMON-LISP:PRINT-OBJECT (VECTOR T) {10005605C3}>

(Спасибо RainerJoswig за указание на то, что список специалистов должен содержать объекты класса, а не символы)

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>)

Так что действительно, вам нужно использовать символ SB-PCL::%GENERIC-FUNCTION:

USER> (slot-value ** 'SB-PCL::%GENERIC-FUNCTION)
#<STANDARD-GENERIC-FUNCTION COMMON-LISP:PRINT-OBJECT (277)>

(напомним, что * и ** — это переменные, представляющие последнее и предпоследнее значения, оцениваемые в REPL)

Примечание

Символ SB-PCL::%GENERIC-FUNCTION для этого слота не экспортируется (для ссылки на него нужны два двоеточия), и он начинается с символа %, что является соглашением для внутренних (иногда опасных) символы. Вы не должны использовать его напрямую; также прямой вызов slot-value не рекомендуется, обычно вам нужны только функции доступа.

method-generic-function

Вместо этого вы должны использовать символы, экспортированные из closer-mop для лучшей совместимости:

(closer-mop:method-generic-function 
  (find-method #'print-object () (mapcar #'find-class '(vector t))))
person coredump    schedule 25.09.2019
comment
(find-method #'print-object () (list 'vector t)) не является переносимым. Вам нужно передать список объектов класса. См. CLHS 7.6.2: Имена специалистов по параметрам используются в макросах, предназначенных для интерфейса пользовательского уровня (defmethod), тогда как специалисты по параметрам используются в функциональном интерфейсе. - person Rainer Joswig; 25.09.2019