У меня проблема с доступом к слотам из определений слотов.Я могу осматривать объекты классов, видеть их определения слотов и даже получать некоторую стандартную информацию об определениях слотов. Однако я не могу получить доступ к пользовательской информации об определении слотов.
Я уже достаточно гуглил этонекоторое время и в итоге прочитал спецификации CLOS & MOP , немного из Lisp Cookbook , о некоторых концепциях MOP и некоторых связанных вопросов на StackOverflow, которые мало чем помогли.Я даже прочитал часть реализаций SBCL , но безрезультатно.
Из частей, которые мне удалось собрать, я могу получить доступ ко многим слотам SLOT DEFINITION
через некоторые функциинапример, получить доступ к NAME
слоту SLOT DEFINITION
, используя CLOSER-MOP:SLOT-DEFINITION-NAME
(что, безусловно, полезно), но я не могу сделать это для слотов, у которых нет одной из этих функций.Например, я не могу получить доступ к слоту REFERENCES
, который предоставляется пакетом MITO
при определении слотов в DEFCLASS
.
Вот минимальный рабочий пример:
(load "~/quicklisp/setup.lisp")
;;;; I'll use MITO because its classes have a funny REFERENCES slot
(quicklisp:quickload :mito)
;;;; I find CLOSER-MOP functions easier to use than
;;;; implementation-specific functions
(quicklisp:quickload :closer-mop)
;;;; Creates a few dummy classes
(defclass example ()
((one-slot :col-type (:varchar 50)
:accessor one-slot-accessor))
(:metaclass mito:dao-table-class)
(:documentation "An example class."))
(defclass another-example ()
((normal-slot :col-type (:varchar 50)
:accessor normal-slot-accessor)
(example-reference :references (example id)
:reader example-reference-accessor))
(:metaclass mito:dao-table-class)
(:documentation "Another example class which references `EXAMPLE' class."))
;;;; Now try to see what's inside those classes
(let* ((class (find-class 'another-example))
(slots (closer-mop:class-direct-slots class))
(slot-i-am-interested (second slots)))
(inspect slot-i-am-interested) ; Oh, apparently we have a REFERENCES slot
;; Why can't SLOT-VALUE access the REFERENCES slot?
(slot-value slot-i-am-interested 'references))
Обратите внимание, что я НЕ обращаюсь к любой базе данных или чему-то подобному, хотя я использую MITO
(я не думаю, что получу эту проблему, если не будуиспользуйте любой пользовательский слот, например, REFERENCES
, который предоставляет MITO
).Это просто манипуляция CLOS / MOP.
Обычный вывод выглядит примерно так (точный вывод зависит от вашей реализации Common Lisp):
user@linuxstudio:~/dev/lisp/slot-question-so$ sbcl --script example.lisp
To load "mito":
Load 1 ASDF system:
mito
; Loading "mito"
....
To load "closer-mop":
Load 1 ASDF system:
closer-mop
; Loading "closer-mop"
The object is a STANDARD-OBJECT of type MITO.DAO.COLUMN:DAO-TABLE-COLUMN-CLASS.
0. SOURCE: #S(SB-C:DEFINITION-SOURCE-LOCATION
:NAMESTRING "/home/user/dev/lisp/slot-question-so/example.lisp"
:INDICES 163840)
1. NAME: EXAMPLE-REFERENCE
2. INITFORM: NIL
3. INITFUNCTION: NIL
4. INITARGS: (:EXAMPLE-REFERENCE)
5. %TYPE: T
6. %DOCUMENTATION: NIL
7. %CLASS: #<MITO.DAO.TABLE:DAO-TABLE-CLASS COMMON-LISP-USER::ANOTHER-EXAMPLE>
8. READERS: (EXAMPLE-REFERENCE-ACCESSOR)
9. WRITERS: NIL
10. ALLOCATION: :INSTANCE
11. ALLOCATION-CLASS: NIL
12. COL-TYPE: NIL
13. REFERENCES: (EXAMPLE ID)
14. PRIMARY-KEY: NIL
15. GHOST: NIL
16. INFLATE: "unbound"
17. DEFLATE: "unbound"
> q
Так что, очевидно, у нас есть REFERENCES
слот.Однако после INSPECT
, когда мы пытаемся SLOT-VALUE
слот, мы получаем ошибку SLOT-MISSING
(показывая только первые строки обратного следа):
Unhandled SIMPLE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING
{10005E85B3}>:
When attempting to read the slot's value (slot-value), the slot REFERENCES is
missing from the object
#<MITO.DAO.COLUMN:DAO-TABLE-COLUMN-CLASS COMMON-LISP-USER::EXAMPLE-REFERENCE>.
Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {10005E85B3}>
0: (SB-DEBUG::DEBUGGER-DISABLED-HOOK #<SIMPLE-ERROR "~@<When attempting to ~A, the slot ~S is missing from the ~
object ~S.~@:>" {1004B1B803}> #<unused argument> :QUIT T)
1: (SB-DEBUG::RUN-HOOK *INVOKE-DEBUGGER-HOOK* #<SIMPLE-ERROR "~@<When attempting to ~A, the slot ~S is missing from the ~
object ~S.~@:>" {1004B1B803}>)
2: (INVOKE-DEBUGGER #<SIMPLE-ERROR "~@<When attempting to ~A, the slot ~S is missing from the ~
object ~S.~@:>" {1004B1B803}>)
3: (ERROR "~@<When attempting to ~A, the slot ~S is missing from the ~
object ~S.~@:>" "read the slot's value (slot-value)" REFERENCES #<MITO.DAO.COLUMN:DAO-TABLE-COLUMN-CLASS COMMON-LISP-USER::EXAMPLE-REFERENCE>)
4: ((:METHOD SLOT-MISSING (T T T T)) #<unused argument> #<MITO.DAO.COLUMN:DAO-TABLE-COLUMN-CLASS COMMON-LISP-USER::EXAMPLE-REFERENCE> REFERENCES SLOT-VALUE NIL) [fast-method]
5: ((LAMBDA (SB-PCL::OBJECT) :IN SB-PCL::SLOT-MISSING-INFO) #<MITO.DAO.COLUMN:DAO-TABLE-COLUMN-CLASS COMMON-LISP-USER::EXAMPLE-REFERENCE>)
6: ((LAMBDA NIL :IN "/home/user/dev/lisp/slot-question-so/example.lisp"))
Так как я могу получить доступ к"слот" REFERENCES
?Это действительно слот?Если нет, как я могу получить к нему доступ?Почему простой SLOT-VALUE
не работает в этом случае?
Можете ли вы указать мне некоторую документацию по этой теме, чтобы предоставить больше информации на случай, если я захочу больше узнать об этом?
Я использую SBCL 1.4.5.debian
в качестве своей реализации lisp, если этоможет быть важным.