[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Issue: LOAD-OBJECTS (Version 1)
This was discussed on the clos and compiler lists. I thought it would
be a good idea to write it up for discussion and give the cleanup group
a look at it. I think it's something that fell in the cracks between
these three subcommittees.
Related issues: none
Edit history: Version 1, 2-Jan-89, by Moon (for discussion)
Common Lisp doesn't provide any way to use an object of a user-defined
type (defined with DEFCLASS or DEFSTRUCT) as a constant in a program
compiled with COMPILE-FILE. The problem is that LOAD has to be able
to "reconstruct" an equivalent object when the compiled-code file is
loaded, but the programmer has no way to tell LOAD how to do that.
Define a new generic function named MAKE-LOAD-FORM, which takes one
argument and returns one value. The value is a form which, when
evaluated at some later time, should return an object that is
equivalent to the argument. The exact meaning of "equivalent"
depends on the type of object and is up to the programmer who
defines a method for MAKE-LOAD-FORM.
Define that COMPILE-FILE calls MAKE-LOAD-FORM on any object that
appears in a constant and has STANDARD-CLASS or STRUCTURE-CLASS as a
metaclass. Define that COMPILE-FILE will only call MAKE-LOAD-FORM
once for any given object (compared with EQ) within a single file.
It is unspecified whether LOAD calls EVAL on the form or does some
other operation that has an equivalent effect.
Define that an instance of a class defined with DEFCLASS without any
direct superclasses, or defined with DEFSTRUCT without the :TYPE or
:INCLUDE options, does not inherit any method for MAKE-LOAD-FORM other
than possibly a method that only signals an error.
(defclass my-class ()
((a :initarg :a :reader my-a)
(b :initarg :b :reader my-b)
(c :accessor my-c)))
(defmethod shared-initialize ((self my-class) ignore &rest ignore)
(unless (slot-boundp self 'c)
(setf (my-c self) (some-computation (my-a self) (my-b self)))))
(defmethod make-load-form ((self my-class))
`(make-instance ',(class-name (class-of self))
:a ',(my-a self) :b ',(my-b self)))
In this example, an equivalent instance of my-class is reconstructed
by using the values of two of its slots. The value of the third slot
is derived from those two values.
(defclass my-frob ()
((name :initarg :name :reader my-name)))
(defmethod make-load-form ((self my-frob))
`(find-my-frob ',(my-name self) :if-does-not-exist :create))
In this example, instances of my-frob are "interned" in some way.
An equivalent instance is reconstructed by using the value of the
name slot as a key for searching existing objects. In this case
the programmer has chosen to create a new object if no existing
object is found; alternatively she could have chosen to signal an
error in that case.
Only the programmer who designed a class can know the correct
way to reconstruct objects of that class at load time, therefore
the reconstruction should be controlled by a generic function.
Using EVAL as the interface for telling LOAD what to do provides
A default method, such as one that makes an object whose class has the
same name and whose slots have equivalent contents, is not supplied
because this is inappropriate for many objects and because it is easy
to write for those objects where it is appropriate.
MAKE-LOAD-FORM has a natural resemblance to PRINT-OBJECT.
Symbolics Flavors has something like this, but under a different name.
The name Symbolics uses is not suitable for standardization.
JonL reports that Lucid is getting more and more requests for this.
Cost to Implementors:
This seems like only a few one-line changes in the compiled-code
file writer and reader.
Cost to Users:
Cost of non-adoption:
Serious impairment of the ability to use extended-type objects. Each
implementation will probably make up its own version of this as an
See Cost of non-adoption.
No significant positive or negative impact.
It would be possible to define an additional level of protocol that
allows multiple classes to contribute to the reconstruction of an
object, combining initialization arguments contributed by each class.
Since a user can easily define that in terms of MAKE-LOAD-FORM without
modifying the Lisp system, it is not being proposed now.
Any type that has a read syntax is likely to appear as a quoted
constant or inside a quoted constant. Pathnames are one example, user
programs often define others. Also many implementations provide a way
to create a compiled-code file full of data (rather than compiled Lisp
programs), and such data probably include extended-type objects.
Moon supports this.