Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

defstruct - :read-only is not read only

In the CLHS I read for :read-only x: "When x is true, this specifies that this slot cannot be altered; it will always contain the value supplied at construction time."

Bit I can do this (CCL, SBCL):

CL-USER> (defstruct foo
           (one 0 :read-only t))
FOO
CL-USER> (defparameter *foo* (make-foo))
*FOO*
CL-USER> *foo*
#S(FOO :ONE 0)
CL-USER> (setf (slot-value *foo* 'one) 1)
1 (1 bit, #x1, #o1, #b1)
CL-USER> *foo*
#S(FOO :ONE 1)

Shouldn't changing this slot be prohibited by Lisp?

like image 742
Manfred Avatar asked Feb 26 '26 07:02

Manfred


2 Answers

slot-value is not how you access the fields of an object whose class was defined with defstruct. Such objects do not portably have named slots at all: they have named accessors.

Some implementations give the fields of such objects names, and may also allow access to them with slot-value: such behaviour is entirely nonportable however.

If you work within the language defined by the standard then you should not be able to modify the value of a structure field defined with a :read-only option.

The specification says:

setf will not accept the reader function for this slot.

slot-value is not the reader function created by defstruct. The reader function is foo-one (unless you override the naming scheme with the :conc-name keyword). So you should get an error if you try to do

(setf (foo-one *foo) 1)
like image 40
Barmar Avatar answered Feb 27 '26 20:02

Barmar