Proper behavior of slot-initforms in defstruct?

Martin Simmons martin at lispworks.com
Tue Aug 4 17:48:22 UTC 2015


>>>>> On Tue, 4 Aug 2015 03:55:30 -0400, Jean-Claude Beaudoin said:
> 
> But I find sad that we'd have to force defstruct to be a top-level only form
> with this workaround instead of letting perfectly normal language constructs
> intermix freely as the problem would find appropriate and natural.
> 
> My interest here is that I am reworking the implementation of the DEFSTRUCT
> macro in MKCL.  And honestly I am of the opinion that there is a pretty
> strong case to be made in favor of the clisp behavior on this issue. But I
> cannot figure out the justification for the other behavior illustrated by
> almost all of the other implementations. Is this just some long standing
> historical quirk at play here or is there really a reason for this way of
> doing it?

Probably because remembering the initform and splicing it into the constructor
of the included defstruct is the most obvious implementation.

It is easy to make that implementation evaluate the initform in the correct
lexical environment by including the constructor in the macroexpansion of
defstruct.  Doing that for included defstructs requires more effort to avoid
slowdown in the simple cases.

Another related case is EQ'ness of the initform values.  For example, with two
files:

q1.lisp:
(defstruct q1 (a '(1 2 3)))
(defun t1 () (eq (q1-a (make-q1)) (q1-a (make-q1))))

q2.lisp:
(defstruct (q2 (:include q1)))
(defun t12 () (eq (q1-a (make-q1)) (q1-a (make-q2))))

If you compile and load each of these files, then t1 should always return t
whereas t12 might return nil or t depending on whether the code for the
initform in q1 is shared or copied.

-- 
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/



More information about the pro mailing list