[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

putting CLOS objects in binfiles



   Date: Fri, 15 Jul 88 17:07 EDT
   From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>

       Date: Fri, 15 Jul 88 12:42:03 PDT
       From: jrose@Sun.COM (John Rose)

       It's a shame that there's no provision in CLOS for
       saving objects in binfiles.
     ...
       Here's essentially what's needed:  A generic function
       (called, say, RECONSTRUCTOR-FORM) which returns a
       Lisp form to evaluate to reconstruct any given
       object.  

   This is fine.  It's how Flavors does it, so there is some
   precedent.  The only problem with this technique is that it
   doesn't cope well with circular structures, which can only
   be handled by separating creation of the objects from filling
   them in (and even that doesn't work in general, for reasons
   too complicated to get into here).
  ...
OK, I'd like to create a proposal.  I understand my hallmate
Cris Perdue is thinking about binfiles, so I'll talk with him
some first.

To deal with circularities, one can separate the object creation
protocol into two passes, one to create a reference to an uninitialized
object (which can be used to plug into other structures), and a second
pass to initialize the object itself.  You say there are in
general problems here, and I imagine you are referring to
the window between the two passes, when the object can be
referenced, but might not yet contain valid data.  Do you
think this problem can be addressed adequately as follows:

  At dump time, if circularities are detected, the target
  of a back-arc (which will need to be created in two passes
  at load time) is passed to a generic function (named, e.g.,
  CIRCULAR-RECONSTRUCTOR-FORMS) which either generates parameters
  for the two load time passes, or signals an error at dump time.

This would allow a class to disallow all or some circularities,
or handle them in a class-specific manner, by gaining some control
over the window between the two load time passes.  An object
in the inter-pass window could even have a different class; pass 2
could perform a CHANGE-CLASS.

Also, let me make another stab at a default behavior for dumping:
Use the PRINT-OBJECT printer, and save the string the binary file.
Proper use of a *PRINT-READABLY* flag would be required to detect errors,
and recursive calls to PRINT-OBJECT would have to transfer
control to the binary dumper (leaving a #<n># or similar
notation in the object's string).  The advantage of this
default is that the class writer need only code a readable
PRINT-OBJECT representation, and not worry about binary files
explicitly.

       Here's my immediate problem:  I want to build objects
       which represent predicates in a special purpose query
       language, and I want them to be uniquified, like pathnames
       on the Lisp Machine.  (They cache things like compiled Lisp
       code, so it's expensive to build new copies.)  Such things
       do not dump properly, and even if a simple patch were to
       be applied (say, to dump a class symbol instead of a class),
       a simple-minded load routine would not uniquify them.

   I'm not sure that anything in Common Lisp requires that multiple
   references to a single object, in a file being compiled, do not
   turn into multiple objects when the file is loaded.

Symbols load as single objects.  And on the Lisp Machine (last
time I looked) pathnames were interned in the same way.
I think this is done because symbols and pathnames are
used as names, or references for other objects, and making
them EQ makes for fast comparison, and allows referencing
parties to make shared annotations on the name object.
					       		You might have
   to address this in an implementation-dependent way unless the
   definition of Common Lisp were changed to require this explicitly.
   I think most implementations do guarantee object identity within
   a single COMPILE-FILE, even though they're not required to.
   This is not a CLOS issue, it applies to all objects for which EQ
   is defined.

I'm willing to guarantee object identity myself, if I can only
get control whenever the system thinks it wants to cons one of
my objects, and intern it.  Something like this:
	(LET ((TABLE (MAKE-HASH-TABLE :TEST 'EQUAL)))
	  (DEFMETHOD MAKE-INSTANCE ((EQL 'MYCLASS) &KEY X Y)
	    (LET ((PARAMS (LIST X Y)))
	      (OR (GETHASH PARAMS TABLE)
		  (SETF (GETHASH PARAMS TABLE)
			(CALL-NEXT-METHOD))))))



   Date: 15 Jul 88 17:08 PDT
   From: Bobrow.pa@Xerox.COM

   In Loops, the way we solved this problem was to provide each savable object a
   unique identifier.  This UID was constructed from some representation of the
   machine of ceation and the time of creation.  An object knows its UID, and from
   the UID one can find the object.  For any object, the form that was dumped
   includes its UID, as well as its contents.  References from a dumped object to
   another object contain a form which reconstructs the pointer to object referred
   to, but does not try to reconstruct its contents.  

Wow!  That's neat stuff.  It shows how far we've come that solutions
to the problem of object identity within a single Lisp session are taken
for granted (reread the CLtL chapter on packages if you think it's
no problem) and the current research is into defining and maintaining
uniqueness across much wider domains, such as all machines and times
in some space.

But all I wanted (this time) was uniqueness across a session, and
some sort of transportable printed representation, like symbols or LispM
pathnames.

					-- John