Lisp 插槽定义的附加属性

Lisp 插槽定义的附加属性,lisp,common-lisp,clos,Lisp,Common Lisp,Clos,说: 实现可以自由地将其他属性添加到 规范化插槽规范,前提是这些不是符号 可在公共lisp用户包中访问,或由任何包导出 在ANSI通用Lisp标准中定义 举个例子: (defclass sst (plane) ((mach mag-step 2 locator sst-mach locator mach-location :reader mach-speed :reader mach))

说:

实现可以自由地将其他属性添加到 规范化插槽规范,前提是这些不是符号 可在公共lisp用户包中访问,或由任何包导出 在ANSI通用Lisp标准中定义

举个例子:

(defclass sst (plane)
     ((mach mag-step 2
            locator sst-mach
            locator mach-location
            :reader mach-speed
            :reader mach))
  (:metaclass faster-class)
  (another-option foo bar))
但当我尝试时:

(defclass a () ((x my-option 123)))
SBCL编译时出错:

初始化参数无效:类调用中的MY-OPTION

                SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION>.    
[SB-PCL类型的条件::INITARG-ERROR]


所以问题来了。如何将其他属性(如“我的选项”)添加到插槽定义中?

实现可以做到这一点。但是用户不能添加随机属性。如果公共Lisp实现支持元对象协议,则可以通过自定义元类添加它。但这意味着还需要提供计算插槽等的方法

这是高级Lisp。《元对象协议的艺术》(The Art of The Metaobject Protocol)一书在第3章中有一个例子,扩展了该语言

一个简单的示例(适用于LispWorks):

让我们在用户定义的类中使用它:

(defclass foo ()
  ((a :initarg :a :foo :bar))
  (:metaclass foo-meta-class))
然后,插槽定义对象将有一个插槽
foo
,其内容为
bar

CL-USER 10 > (find-class 'foo)
#<FOO-META-CLASS FOO 42200995AB>

CL-USER 11 > (class-direct-slots *)
(#<FOO-STANDARD-DIRECT-SLOT-DEFINITION A 42200B4C7B>)

CL-USER 12 > (describe (first *))

#<FOO-STANDARD-DIRECT-SLOT-DEFINITION A 42200B4C7B> is a FOO-STANDARD-DIRECT-SLOT-DEFINITION
FOO                     :BAR
READERS                 NIL
WRITERS                 NIL
NAME                    A
INITFORM                NIL
INITFUNCTION            NIL
TYPE                    T
FLAGS                   1
INITARGS                (:A)
ALLOCATION              :INSTANCE
DOCUMENTATION-SLOT      NIL
CL-USER 10>(查找类“foo”)
#
CL-USER 11>(类直接插槽*)
(#)
CL-USER 12>(描述(第一*)
#是一个FOO-STANDARD-DIRECT-SLOT-DEFINITION
福:酒吧
读者零
作家零
说出一个
初始形式零
初始化函数NIL
T型
旗帜1
INITARGS(:A)
分配:实例
无槽文件

很明显,如果财产有任何实际意义的话,还有更多的内容。

谢谢!此示例在lispworks中运行良好。但是对于SBCL和closer mop,它返回一个错误:“类被指定为类的超类,但是元类和不兼容。为SB-mop定义一个方法:VALIDATE-SUPERCLASS以避免此错误。[类型SIMPLE-error的条件]”,您只需要完全按照它的说明执行:
(defmethod VALIDATE SUPERCLASS((类foo元类)(超类标准类))t@user1312837:LispWorks仅当
foo meta class
meta class不是
标准类的子类时才需要
validate superclass
。这很有意义。对于SBCL,只需添加Philipp提到的方法即可。@RainerJoswig有趣的是,至少在SBCL中这样做时,我可以获得di上的foo槽的值rect插槽定义,但是有效插槽定义上的foo值仍然为零。defclass表单似乎没有正确初始化有效插槽中的foo。在LispWorks personal 6.1.1中也确认了这一点。我必须搜索AMOP以寻找线索。
CL-USER 10 > (find-class 'foo)
#<FOO-META-CLASS FOO 42200995AB>

CL-USER 11 > (class-direct-slots *)
(#<FOO-STANDARD-DIRECT-SLOT-DEFINITION A 42200B4C7B>)

CL-USER 12 > (describe (first *))

#<FOO-STANDARD-DIRECT-SLOT-DEFINITION A 42200B4C7B> is a FOO-STANDARD-DIRECT-SLOT-DEFINITION
FOO                     :BAR
READERS                 NIL
WRITERS                 NIL
NAME                    A
INITFORM                NIL
INITFUNCTION            NIL
TYPE                    T
FLAGS                   1
INITARGS                (:A)
ALLOCATION              :INSTANCE
DOCUMENTATION-SLOT      NIL