defstructのスロットに:read-onlyオプションを付けますが、SBCL等ではスロットに書き込めてしまいます。 他の処理系では、セッターを定義しないことで書き込みをしにくくしているようですが、 なにかもっと良い方法はないのでしょうか。

(defstruct foo (x nil :read-only t) y z)


(setf (foo-x (make-foo :x 9)) 8)
;sbcl =>  8
;!> allegro: `(SETF FOO-X)' is not fbound
;!> ecl: The function (SETF FOO-X) is undefined.
;!> clisp: FUNCALL: undefined function |(SETF COMMON-LISP-USER:FOO-X)|


;; ※ANSI CL仕様外
(setf (slot-value (make-foo :x 9) 'x) 8)
;=>  8

エラーを出すようセッターを定義する位しかないのでしょうか。

(defun (setf foo-x) (val foo)
  (declare (ignore val))
  (error "~S: attempt to write a readonly slot: X" foo))


;; ※ANSI CL仕様外
(defmethod (setf c2mop:slot-value-using-class)
           (val
            (class (eql (find-class 'foo)))
            (obj foo)
            (slotd
             (eql
              (find 'x (c2mop:class-slots (find-class 'foo))
               :key #'c2mop:slot-definition-name))))
  (error "~S: attempt to write a readonly slot: X" obj))