defclass の slot には、:type オプションを指定することができる。
期待としては、:type オプションを指定した場合、指定した型を満たさない値を代入しようとすると、エラーとなって欲しい。ところが、SBCL ではそのようにならない。
(defclass foo () ((x :accessor foo-x :initarg :x :type integer))) (let ((x (make-instance 'foo :x 1))) (setf (foo-x x) :foo) (foo-x x)) ; => :foo
defclass と slot へのアクセスを optimize safety で評価すると、期待する挙動となる。
(locally (declare (optimize safety)) (defclass foo () ((x :accessor foo-x :initarg :x :type integer))) (let ((x (make-instance 'foo :x 1))) (setf (foo-x x) :foo) ; error (foo-x x)))
CLHSには、以下のようにあるものの、
The consequences of attempting to store in a slot a value that does not satisfy the type of the slot are undefined.
その前の部分には以下のようにある。
The :type slot option specifies that the contents of the slot will always be of the specified data type.
SBCL User Manualには以下のようにあり、その理由は示されていない。悲しい。
Types declared using the :type slot option in defclass are asserted if and only if the class was defined in safe code and the slot access location is in safe code as well.