1
0
Fork 0
cl-sites/HyperSpec-7-0/HyperSpec/Issues/iss215_w.htm
2024-04-01 10:24:07 +02:00

319 lines
24 KiB
HTML

<!-- Common Lisp HyperSpec (TM), version 7.0 generated by Kent M. Pitman on Mon, 11-Apr-2005 2:31am EDT -->
<HTML>
<HEAD>
<TITLE>CLHS: Issue LOAD-OBJECTS Writeup</TITLE>
<LINK HREF="../Data/clhs.css" REL="stylesheet" TYPE="text/css" />
<META HTTP-EQUIV="Author" CONTENT="Kent M. Pitman">
<META HTTP-EQUIV="Organization" CONTENT="LispWorks Ltd.">
<LINK REL=TOP HREF="../Front/index.htm">
<LINK REL=COPYRIGHT HREF="../Front/Help.htm#Legal">
<LINK REL=DISCLAIMER HREF="../Front/Help.htm#Disclaimer">
<LINK REL=PREV HREF="../Issues/iss214_w.htm">
<LINK REL=UP HREF="../Issues/iss215.htm">
<LINK REL=NEXT HREF="../Issues/iss216_w.htm">
</HEAD>
<BODY>
<H1><A REV=MADE HREF="http://www.lispworks.com/"><IMG WIDTH=80 HEIGHT=65 ALT="[LISPWORKS]" SRC="../Graphics/LWSmall.gif" ALIGN=Bottom></A><A REL=TOP HREF="../Front/index.htm"><IMG WIDTH=237 HEIGHT=65 ALT="[Common Lisp HyperSpec (TM)]" SRC="../Graphics/CLHS_Sm.gif" ALIGN=Bottom></A> <A REL=PREV HREF="../Issues/iss214_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="../Issues/iss215.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="../Issues/iss216_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
<HR>
<H2>Issue LOAD-OBJECTS Writeup</H2>
<PRE><B>Issue:</B> <A HREF="iss215.htm">LOAD-OBJECTS</A><P>
<P>
<B>References:</B> none<P>
<P>
Related issues: <A HREF="iss216_m.htm">LOAD-TIME-EVAL</A>,<P>
<A HREF="iss081.htm">CONSTANT-COMPILABLE-TYPES</A>,<P>
<A HREF="iss079.htm">CONSTANT-CIRCULAR-COMPILATION</A><P>
<P>
<B>Category:</B> ADDITION<P>
<P>
<B>Forum:</B> Cleanup<P>
<P>
<B>Edit history:</B> Version 1, 2-Jan-89, by Moon (for discussion)<P>
Version 2, 13-Jan-89, by Moon (draft updated from discussion)<P>
Version 3, 9-Mar-89, by Moon (changes suggested by discussion)<P>
Version 4, 4-Apr-89, by Pitman (changes per X3J13 Mar 89; <P>
MAKE-LOAD-FORM-USING-SLOTS =&gt; <A REL=DEFINITION HREF="../Body/f_mk_l_1.htm#make-load-form-saving-slots"><B>MAKE-LOAD-FORM-SAVING-SLOTS</B></A>)<P>
<P>
<B>Status:</B> Accepted by an 18-0 vote, March 1989.<P>
<P>
<B>Problem description:<P>
</B><P>
Common Lisp doesn't <A REL=DEFINITION HREF="../Body/f_provid.htm#provide"><B>provide</B></A> any way to use an object of a user-defined<P>
type (defined with <A REL=DEFINITION HREF="../Body/m_defcla.htm#defclass"><B>DEFCLASS</B></A> or <A REL=DEFINITION HREF="../Body/m_defstr.htm#defstruct"><B>DEFSTRUCT</B></A>) as a constant in a program<P>
compiled with <A REL=DEFINITION HREF="../Body/f_cmp_fi.htm#compile-file"><B>COMPILE-FILE</B></A>. The problem is that <A REL=DEFINITION HREF="../Body/f_load.htm#load"><B>LOAD</B></A> has to be able<P>
to &quot;reconstruct&quot; an equivalent object when the compiled-code file is<P>
loaded, but the programmer has no way to tell <A REL=DEFINITION HREF="../Body/f_load.htm#load"><B>LOAD</B></A> how to do that.<P>
<P>
<P>
<B>Proposal (LOAD-OBJECTS:MAKE-LOAD-FORM):<P>
</B> <P>
Define a new generic function named <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A>, which takes one<P>
argument and returns two values. The argument is an object that is<P>
referenced as a constant or as a self-evaluating form in a file being<P>
compiled by <A REL=DEFINITION HREF="../Body/f_cmp_fi.htm#compile-file"><B>COMPILE-FILE</B></A>. The objective is to enable <A REL=DEFINITION HREF="../Body/f_load.htm#load"><B>LOAD</B></A> to<P>
construct an equivalent object.<P>
<P>
The first value, called the &quot;creation form,&quot; is a form that, when<P>
evaluated at load time, should return an object that is equivalent to<P>
the argument. The exact meaning of &quot;equivalent&quot; depends on the type<P>
of object and is up to the programmer who defines a <A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A> for<P>
<A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A>. This is the same type of equivalence discussed<P>
in issue <A HREF="iss081.htm">CONSTANT-COMPILABLE-TYPES</A>.<P>
<P>
The second value, called the &quot;initialization form,&quot; is a form that,<P>
when evaluated at load time, should perform further initialization of<P>
the object. The value returned by the initialization form is ignored.<P>
If the <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> <A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A> returns only one value, the<P>
initialization form is <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>, which has no effect. If the object used<P>
as the argument to <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> appears as a constant in the<P>
initialization form, at load time it will be replaced by the<P>
equivalent object constructed by the creation form; this is how the<P>
further initialization gains access to the object.<P>
<P>
Both the creation form and the initialization form can contain<P>
references to objects of user-defined types (defined precisely below).<P>
However, there must not be any circular dependencies in creation forms.<P>
An example of a circular dependency is when the creation form for the<P>
object X contains a reference to the object Y, and the creation form<P>
for the object Y contains a reference to the object X. A simpler<P>
example would be when the creation form for the object X contains<P>
a reference to X itself. Initialization forms are not subject to<P>
any restriction against circular dependencies, which is the entire<P>
reason that initialization forms exist. See the example of circular<P>
data structures below.<P>
<P>
The creation form for an object is always evaluated before the<P>
initialization form for that object. When either the creation form or<P>
the initialization form references other objects of user-defined types<P>
that have not been referenced earlier in the <A REL=DEFINITION HREF="../Body/f_cmp_fi.htm#compile-file"><B>COMPILE-FILE</B></A>, the<P>
compiler collects all of the creation and initialization forms. Each<P>
initialization form is evaluated as soon as possible after its<P>
creation form, as determined by data flow. If the initialization form<P>
for an object does not reference any other objects of user-defined<P>
types that have not been referenced earlier in the <A REL=DEFINITION HREF="../Body/f_cmp_fi.htm#compile-file"><B>COMPILE-FILE</B></A>, the<P>
initialization form is evaluated immediately after the creation form.<P>
If a creation or initialization form F references other objects of<P>
user-defined types that have not been referenced earlier in the<P>
<A REL=DEFINITION HREF="../Body/f_cmp_fi.htm#compile-file"><B>COMPILE-FILE</B></A>, the creation forms for those other objects are evaluated<P>
before F, and the initialization forms for those other objects are<P>
also evaluated before F whenever they do not depend on the object<P>
created or initialized by F. Where the above rules do not uniquely<P>
determine an order of evaluation, which of the possible orders of<P>
evaluation is chosen is unspecified.<P>
<P>
While these creation and initialization forms are being evaluated, the<P>
objects are possibly in an uninitialized state, analogous to the state<P>
of an object between the time it has been created by <A REL=DEFINITION HREF="../Body/f_alloca.htm#allocate-instance"><B>ALLOCATE-INSTANCE</B></A><P>
and it has been processed fully by <A REL=DEFINITION HREF="../Body/f_init_i.htm#initialize-instance"><B>INITIALIZE-INSTANCE</B></A>. Programmers<P>
writing methods for <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> must take care in manipulating<P>
objects not to depend on slots that have not yet been initialized.<P>
<P>
It is unspecified whether <A REL=DEFINITION HREF="../Body/f_load.htm#load"><B>LOAD</B></A> calls <A REL=DEFINITION HREF="../Body/f_eval.htm#eval"><B>EVAL</B></A> on the forms or does some<P>
other operation that has an equivalent effect. For example, the<P>
forms might be translated into different but equivalent forms and<P>
then evaluated, they might be compiled and the resulting functions<P>
called by <A REL=DEFINITION HREF="../Body/f_load.htm#load"><B>LOAD</B></A>, or they might be interpreted by a special-purpose<P>
interpreter different from <A REL=DEFINITION HREF="../Body/f_eval.htm#eval"><B>EVAL</B></A>. All that is required is that the<P>
effect be equivalent to evaluating the forms.<P>
<P>
<A REL=DEFINITION HREF="../Body/f_cmp_fi.htm#compile-file"><B>COMPILE-FILE</B></A> calls <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> on any object that is referenced as<P>
a constant or as a self-evaluating form, if the object's metaclass is<P>
<A REL=DEFINITION HREF="../Body/t_std_cl.htm#standard-class"><B>STANDARD-CLASS</B></A>, <A REL=DEFINITION HREF="../Body/t_stu_cl.htm#structure-class"><B>STRUCTURE-CLASS</B></A>, any user-defined metaclass (not a<P>
subclass of <A REL=DEFINITION HREF="../Body/t_built_.htm#built-in-class"><B>BUILT-IN-CLASS</B></A>), or any of a possibly-empty<P>
implementation-defined list of other metaclasses. <A REL=DEFINITION HREF="../Body/f_cmp_fi.htm#compile-file"><B>COMPILE-FILE</B></A> will<P>
only call <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> once for any given object (compared with <A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A>)<P>
within a single file.<P>
<P>
It is valid for user programs to call <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> in other<P>
circumstances, providing the argument's metaclass is not <A REL=DEFINITION HREF="../Body/t_built_.htm#built-in-class"><B>BUILT-IN-CLASS</B></A><P>
or a subclass of <A REL=DEFINITION HREF="../Body/t_built_.htm#built-in-class"><B>BUILT-IN-CLASS</B></A>.<P>
<P>
Define a new function named <A REL=DEFINITION HREF="../Body/f_mk_l_1.htm#make-load-form-saving-slots"><B>MAKE-LOAD-FORM-SAVING-SLOTS</B></A>, which takes<P>
one required argument and one optional argument and returns two<P>
values. This can be useful in user-written <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> methods.<P>
The first argument is the object. The optional second argument is a<P>
list of the names of the slots to preserve; it defaults to all of the<P>
local slots. <A REL=DEFINITION HREF="../Body/f_mk_l_1.htm#make-load-form-saving-slots"><B>MAKE-LOAD-FORM-SAVING-SLOTS</B></A> returns forms that construct<P>
an equivalent object using <A REL=DEFINITION HREF="../Body/f_mk_ins.htm#make-instance"><B>MAKE-INSTANCE</B></A> and <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> of <A REL=DEFINITION HREF="../Body/f_slt_va.htm#slot-value"><B>SLOT-VALUE</B></A> for<P>
slots with values, or <A REL=DEFINITION HREF="../Body/f_slt_ma.htm#slot-makunbound"><B>SLOT-MAKUNBOUND</B></A> for slots without values, or<P>
using other functions of equivalent effect.<P>
<A REL=DEFINITION HREF="../Body/f_mk_l_1.htm#make-load-form-saving-slots"><B>MAKE-LOAD-FORM-SAVING-SLOTS</B></A> returns two values, thus it can deal with<P>
circular structures. <A REL=DEFINITION HREF="../Body/f_mk_l_1.htm#make-load-form-saving-slots"><B>MAKE-LOAD-FORM-SAVING-SLOTS</B></A> works for any object<P>
of metaclass <A REL=DEFINITION HREF="../Body/t_std_cl.htm#standard-class"><B>STANDARD-CLASS</B></A> or <A REL=DEFINITION HREF="../Body/t_stu_cl.htm#structure-class"><B>STRUCTURE-CLASS</B></A>. Whether the result is<P>
useful in an application depends on whether the object's type and slot<P>
contents fully capture the application's idea of the object's state.<P>
<P>
<A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> of an object of metaclass <A REL=DEFINITION HREF="../Body/t_std_cl.htm#standard-class"><B>STANDARD-CLASS</B></A> or<P>
<A REL=DEFINITION HREF="../Body/t_stu_cl.htm#structure-class"><B>STRUCTURE-CLASS</B></A> for which no user-defined <A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A> is applicable signals<P>
an error. It is valid to implement this either by defining default<P>
methods on <A REL=DEFINITION HREF="../Body/t_std_ob.htm#standard-object"><B>STANDARD-OBJECT</B></A> and <A REL=DEFINITION HREF="../Body/t_stu_ob.htm#structure-object"><B>STRUCTURE-OBJECT</B></A> that signal an error<P>
or by having no applicable <A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A> for those classes.<P>
<P>
<P>
<B>Examples:<P>
</B><P>
;; Example 1<P>
(<A REL=DEFINITION HREF="../Body/m_defcla.htm#defclass"><B>defclass</B></A> my-class ()<P>
((a :initarg :a :reader my-a)<P>
(b :initarg :b :reader my-b)<P>
(c :accessor my-c)))<P>
(<A REL=DEFINITION HREF="../Body/m_defmet.htm#defmethod"><B>defmethod</B></A> <A REL=DEFINITION HREF="../Body/f_shared.htm#shared-initialize"><B>shared-initialize</B></A> ((self my-class) <A REL=DEFINITION HREF="../Body/d_ignore.htm#ignore"><B>ignore</B></A> <A REL=DEFINITION HREF="../Body/03_da.htm#AMrest"><B>&amp;rest</B></A> <A REL=DEFINITION HREF="../Body/d_ignore.htm#ignore"><B>ignore</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> (<A REL=DEFINITION HREF="../Body/f_slt_bo.htm#slot-boundp"><B>slot-boundp</B></A> self 'c)<P>
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>setf</B></A> (my-c self) (some-computation (my-a self) (my-b self)))))<P>
(<A REL=DEFINITION HREF="../Body/m_defmet.htm#defmethod"><B>defmethod</B></A> <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>make-load-form</B></A> ((self my-class))<P>
`(<A REL=DEFINITION HREF="../Body/f_mk_ins.htm#make-instance"><B>make-instance</B></A> ',(<A REL=DEFINITION HREF="../Body/f_class_.htm#class-name"><B>class-name</B></A> (<A REL=DEFINITION HREF="../Body/f_clas_1.htm#class-of"><B>class-of</B></A> self))<P>
:a ',(my-a self) :b ',(my-b self)))<P>
<P>
In this example, an equivalent instance of my-class is reconstructed<P>
by using the values of two of its slots. The value of the third slot<P>
is derived from those two values.<P>
<P>
Another way to write the last form in the above example would have been<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defmet.htm#defmethod"><B>defmethod</B></A> <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>make-load-form</B></A> ((self my-class))<P>
(<A REL=DEFINITION HREF="../Body/f_mk_l_1.htm#make-load-form-saving-slots"><B>make-load-form-saving-slots</B></A> self '(a b)))<P>
<P>
;; Example 2<P>
(<A REL=DEFINITION HREF="../Body/m_defcla.htm#defclass"><B>defclass</B></A> my-frob ()<P>
((name :initarg :name :reader my-name)))<P>
(<A REL=DEFINITION HREF="../Body/m_defmet.htm#defmethod"><B>defmethod</B></A> <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>make-load-form</B></A> ((self my-frob))<P>
`(find-my-frob ',(my-name self) :if-does-not-exist :create))<P>
<P>
In this example, instances of my-frob are &quot;interned&quot; in some way.<P>
An equivalent instance is reconstructed by using the value of the<P>
name slot as a key for searching existing objects. In this case<P>
the programmer has chosen to create a new object if no existing<P>
object is found; alternatively she could have chosen to signal an<P>
error in that case.<P>
<P>
;; Example 3<P>
(<A REL=DEFINITION HREF="../Body/m_defcla.htm#defclass"><B>defclass</B></A> tree-with-parent () ((parent :accessor tree-parent)<P>
(children :initarg :children)))<P>
(<A REL=DEFINITION HREF="../Body/m_defmet.htm#defmethod"><B>defmethod</B></A> <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>make-load-form</B></A> ((x tree-with-parent))<P>
(<A REL=DEFINITION HREF="../Body/a_values.htm#values"><B>values</B></A><P>
;; creation form<P>
`(<A REL=DEFINITION HREF="../Body/f_mk_ins.htm#make-instance"><B>make-instance</B></A> ',(<A REL=DEFINITION HREF="../Body/f_clas_1.htm#class-of"><B>class-of</B></A> x) :children ',(<A REL=DEFINITION HREF="../Body/f_slt_va.htm#slot-value"><B>slot-value</B></A> x 'children))<P>
;; initialization form<P>
`(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>setf</B></A> (tree-parent ',x) ',(<A REL=DEFINITION HREF="../Body/f_slt_va.htm#slot-value"><B>slot-value</B></A> x 'parent))))<P>
<P>
In this example, the data <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A> to be dumped is circular, because<P>
each parent has a list of its children and each child has a reference<P>
back to its parent. Suppose <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>make-load-form</B></A> is called on one object in<P>
such a <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A>. The creation form creates an equivalent object and<P>
fills in the children slot, which forces creation of equivalent<P>
objects for all of its children, grandchildren, etc. At this point<P>
none of the parent slots have been filled in. The initialization form<P>
fills in the parent slot, which forces creation of an equivalent<P>
object for the parent if it was not already created. Thus the entire<P>
tree is recreated at load time. At compile time, <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> is<P>
called once for each object in the true. All of the creation forms<P>
are evaluated, in unspecified order, and then all of the<P>
initialization forms are evaluated, also in unspecified order.<P>
<P>
;; Example 4<P>
(<A REL=DEFINITION HREF="../Body/m_defstr.htm#defstruct"><B>defstruct</B></A> my-struct a b c)<P>
(<A REL=DEFINITION HREF="../Body/m_defmet.htm#defmethod"><B>defmethod</B></A> <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>make-load-form</B></A> ((s my-struct))<P>
(<A REL=DEFINITION HREF="../Body/f_mk_l_1.htm#make-load-form-saving-slots"><B>make-load-form-saving-slots</B></A> s))<P>
<P>
In this example, the data <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A> to be dumped has no special<P>
properties and an equivalent <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A> can be reconstructed<P>
simply by reconstructing the slots' contents.<P>
<P>
<P>
<B>Rationale:<P>
</B><P>
Only the programmer who designed a <A REL=DEFINITION HREF="../Body/t_class.htm#class"><B>class</B></A> can know the correct<P>
way to reconstruct objects of that <A REL=DEFINITION HREF="../Body/t_class.htm#class"><B>class</B></A> at load time, therefore<P>
the reconstruction should be controlled by a generic function.<P>
Using <A REL=DEFINITION HREF="../Body/f_eval.htm#eval"><B>EVAL</B></A> as the interface for telling <A REL=DEFINITION HREF="../Body/f_load.htm#load"><B>LOAD</B></A> what to do provides<P>
full generality.<P>
<P>
<A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> returns two values so that circular structures can<P>
be handled. If <A HREF="iss079.htm">CONSTANT-CIRCULAR-COMPILATION</A> is rejected,<P>
<A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> will only return one value, although implementations<P>
that make an extension to support circular constants will probably<P>
also make the extension to accept two values from <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A>.<P>
<P>
The default for <A REL=DEFINITION HREF="../Body/t_class.htm#class"><B>class</B></A> objects and structures is to signal an error,<P>
rather than picking some particular object reconstruction technique,<P>
because no reconstruction technique is appropriate for all objects.<P>
It only takes two lines of code, as in example 4, to instruct the<P>
compiler to use the technique that most often has been suggested<P>
as the default.<P>
<P>
<A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> has a natural resemblance to <A REL=DEFINITION HREF="../Body/f_pr_obj.htm#print-object"><B>PRINT-OBJECT</B></A>, as a hook<P>
for the programmer to control the system's actions.<P>
<P>
The order of evaluation rules for creation and initialization forms<P>
eliminate the possibility of partially initialized objects in the<P>
absence of circular structures, and reduce it to the minimum possible<P>
in the presence of circular structures. This allows nodes in<P>
non-circular structures to be built out of fully initialized subparts.<P>
<P>
<P>
<B>Current practice:<P>
</B><P>
Symbolics Flavors has something like this, but under a different name.<P>
The name Symbolics uses is not suitable for standardization.<P>
<P>
JonL reports that Lucid is getting more and more requests for this.<P>
<P>
<B>Cost to Implementors:<P>
</B><P>
This seems like only a few one-line changes in the compiled-code<P>
file writer and reader. <A REL=DEFINITION HREF="../Body/f_mk_l_1.htm#make-load-form-saving-slots"><B>MAKE-LOAD-FORM-SAVING-SLOTS</B></A> is a couple<P>
dozen lines of code, assuming the presence of the CLOS metaobject<P>
protocol or an implementation-dependent equivalent.<P>
<P>
<B>Cost to Users:<P>
</B><P>
None.<P>
<P>
<B>Cost of non-adoption:<P>
</B><P>
Serious impairment of the ability to use extended-type objects. Each<P>
implementation will probably make up its own version of this as an<P>
extension.<P>
<P>
<B>Performance impact:<P>
</B><P>
None.<P>
<P>
<B>Benefits:<P>
</B><P>
See Cost of non-adoption.<P>
<P>
<B>Esthetics:<P>
</B><P>
No significant positive or negative impact.<P>
<P>
<B>Discussion:<P>
</B><P>
It would be possible to define an additional level of protocol that<P>
allows multiple classes to contribute to the reconstruction of an<P>
object, combining initialization arguments contributed by each <A REL=DEFINITION HREF="../Body/t_class.htm#class"><B>class</B></A>.<P>
Since a user can easily define that in terms of <A REL=DEFINITION HREF="../Body/f_mk_ld_.htm#make-load-form"><B>MAKE-LOAD-FORM</B></A> without<P>
modifying the Lisp system, it is not being proposed now.<P>
<P>
Any type that has a read syntax is likely to appear as a quoted<P>
constant or inside a quoted constant. Pathnames are one example, user<P>
programs often define others. Also many implementations <A REL=DEFINITION HREF="../Body/f_provid.htm#provide"><B>provide</B></A> a way<P>
to create a compiled-code file full of data (rather than compiled Lisp<P>
programs), and such data probably include extended-type objects.<P>
<P>
Moon supports this. David Gray and John Rose made major contributions<P>
to the discussion that produced this improved version 2 proposal.<P>
<P>
</PRE>
<HR>
<A REL=NAVIGATOR HREF="../Front/StartPts.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Starting Points]" SRC="../Graphics/StartPts.gif" ALIGN=Bottom></A><A REL=TOC HREF="../Front/Contents.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Contents]" SRC="../Graphics/Contents.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Master.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Index]" SRC="../Graphics/Index.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Symbol.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Symbols]" SRC="../Graphics/Symbols.gif" ALIGN=Bottom></A><A REL=GLOSSARY HREF="../Body/26_a.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Glossary]" SRC="../Graphics/Glossary.gif" ALIGN=Bottom></A><A HREF="../Front/X3J13Iss.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Issues]" SRC="../Graphics/Issues.gif" ALIGN=Bottom></A><BR>
<A REL=COPYRIGHT HREF="../Front/Help.htm#Legal"><I>Copyright 1996-2005, LispWorks Ltd. All rights reserved.</I></A><P>
</BODY>
</HTML>