据说,只有公共Lisp中的特殊变量才能被解除约束。对于所有词法变量,默认值为nil。我认为类插槽存在于类似闭包的地方,但显然它们不存在。
如果我定义一个没有:initform参数的CLOS插槽(希望它们无论如何都绑定到nil ),并且在创建实例时不提供值,我将得到一个带有未绑定插槽的实例。为甚麽会这样?不方便。
发布于 2014-06-22 08:47:42
CLOS实例不是闭包
CLOS实例通常不是作为闭包实现的。那就很难了。它们是一些数据结构,具有类似于插槽向量的东西。类似于通用Lisp的结构。CLOS实例和结构之间的差异使其复杂化: CLOS实例有可能在运行时更改槽数,并且可以在运行时更改CLOS实例的类。
确保插槽有一个NIL 值的
使用一些先进的CLOS,您可以确保插槽有一个零值。注意,在我的示例中,包CLOS中的函数可能位于CL中的另一个包中。
此函数查找实例的所有插槽。如果一个插槽未绑定,它将被设置为NIL。
(defun set-all-unbound-slots (instance &optional (value nil))
(let ((class (class-of instance)))
(clos:finalize-inheritance class)
(loop for slot in (clos:class-slots class)
for name = (clos:slot-definition-name slot)
unless (slot-boundp instance name)
do (setf (slot-value instance name) value))
instance))我们做了一个混合班:
(defclass set-unbound-slots-mixin () ())修补程序将在初始化对象后运行。
(defmethod initialize-instance :after ((i set-unbound-slots-mixin) &rest initargs)
(set-all-unbound-slots i nil))示例
(defclass c1 (set-unbound-slots-mixin)
((a :initform 'something)
b
c))
CL-USER 1 > (describe (make-instance 'c1))
#<C1 4020092AEB> is a C1
A SOMETHING
B NIL
C NIL发布于 2014-06-24 12:45:36
对于像按需计算时隙值这样的事情来说,它非常方便,在这种情况下,值有时可能为零。当访问未绑定时隙时,CLOS通常调用SLOT-UNBOUND泛型函数,这表示错误。但是,您可以将SLOT-UNBOUND专门化为按需计算和存储值,而不是错误。后续访问将直接使用时隙值,您可以使用SLOT-MAKUNBOUND刷新槽“缓存”。
您可以使用某个类型的前哨“非绑定”值来完成这一任务,但是使用内置的功能非常方便。
slot-unbound使用示例:
(defclass foo ()
((bar :accessor bar)
(baz :accessor baz)))
(defmethod slot-unbound (class (instance foo) slot-name)
(declare (ignorable class))
(setf (slot-value instance slot-name) nil))在行动中:
CL-USER> (defparameter *foo* (make-instance 'foo))
*FOO*
CL-USER> (bar *foo*)
NIL
CL-USER> (setf (baz *foo*) (not (baz *foo*)))
Thttps://stackoverflow.com/questions/24348474
复制相似问题