如何访问元对象/插槽定义插槽?为什么`slot-value`可以访问对象的插槽,但不能访问元对象的插槽?

时间:2019-02-14 20:23:44

标签: common-lisp clos mop

我在从插槽定义中取出插槽时遇到问题。我可以检查类对象,查看其插槽定义,甚至可以获取有关插槽定义的一些标准信息。但是,我无法访问有关插槽定义的用户定义信息。

我已经在Google上搜索了一段时间,最终阅读了CLOS & MOP specificationsLisp Cookbook,约MOP conceptssome {{3 }} related questions StackOverflow并没有太大帮助。我什至读了一段on,但无济于事。

从我能够拼凑而成的作品中,我可以通过一些功能(例如,使用SLOT DEFINITION访问NAME的{​​{1}}插槽(这很有用),但是对于没有这些功能之一的插槽,我不能这样做。例如,在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)。只是普通的CLOS / MOP操作。

通常的输出类似于(确切的输出取决于您的Common Lisp实现):

REFERENCES

因此,显然,我们确实有一个MITO插槽。但是,在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作为lisp的实现。

1 个答案:

答案 0 :(得分:4)

插槽名称是符号,因此使用SLOT-VALUE / WITH-SLOTS时,包装很重要。在这种情况下,引用槽似乎由软件包MITO.CLASS.COLUMN中的内部符号命名。

检查器没有显示软件包名称(因为很少使用),但是您可以看到插槽定义为MITO.DAO.COLUMN:DAO-TABLE-COLUMN-CLASS类型,因此您可以使用CLOSER-MOP:CLASS-SLOTS查找插槽定义:

CL-USER> (closer-mop:class-slots (find-class 'MITO.DAO.COLUMN:DAO-TABLE-COLUMN-CLASS))
(#<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::SOURCE>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::NAME>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::INITFORM>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::INITFUNCTION>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::INITARGS>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::%TYPE>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::%DOCUMENTATION>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::%CLASS>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::READERS>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::WRITERS>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::ALLOCATION>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION SB-PCL::ALLOCATION-CLASS>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION MITO.CLASS.COLUMN::COL-TYPE>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION MITO.CLASS.COLUMN::REFERENCES>   ;<-- HERE
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION MITO.CLASS.COLUMN::PRIMARY-KEY>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION MITO.CLASS.COLUMN::GHOST>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION MITO.DAO.COLUMN::INFLATE>
 #<SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION MITO.DAO.COLUMN::DEFLATE>)

或者,您可以尝试(apropos "references")来查看所有带有此类符号的软件包:

CL-USER> (apropos "references")
REFERENCES
:HAS-EXTERNAL-REFERENCES-P (bound)
:REFERENCES (bound)
MITO.CLASS.COLUMN::REFERENCES  ;<-- HERE
MITO.CLASS.COLUMN:TABLE-COLUMN-REFERENCES (fbound)
MITO.CLASS.COLUMN:TABLE-COLUMN-REFERENCES-COLUMN (fbound)
...