Как указать на дефгенерический экземпляр в CLOS с общим списком - PullRequest
1 голос
/ 25 сентября 2019

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

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

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

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

1 Ответ

3 голосов
/ 25 сентября 2019

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