319 lines
24 KiB
HTML
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 => <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 "reconstruct" 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 "creation form," 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 "equivalent" 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 "initialization form," 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>&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 "interned" 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>
|