[comp.lang.clos] Copying objects

djk@cs.columbia.edu (David Kurlander) (11/27/90)

Is there a way to copy an instance of an object?  Something similar to
the structure copiers generated for defstructs?  I'd hate to have to
define a specific method for each class.

Thanks,
David
-- 
----------------------------------
David Kurlander				Department of Computer Science
djk@cs.columbia.edu			Columbia University

barmar@think.com (Barry Margolin) (11/27/90)

In article <1990Nov26.192413.23214@cs.columbia.edu> djk@cs.columbia.edu (David Kurlander) writes:
>Is there a way to copy an instance of an object?  Something similar to
>the structure copiers generated for defstructs?  I'd hate to have to
>define a specific method for each class.

No, there is no standard copying function, and this was intentionally
omitted.  The same goes for equivalence functions (although we might have
given in and defined EQUALP for CLOS objects, I don't remember).  The
appropriate behavior of a copying or equivalence function is generally
application-dependent.  Should the copy be deep (copying the entire
structure, sharing pointers to leaves, a la copy-tree) or shallow (copying
only the top-level structure, like copy-list)?  If deep, what types of
objects are leaves (for copy-tree it's simple -- anything but a cons is a
leaf).  What do you get when you pass an instance of a subclass to a
superclass's copier (we almost got rid of DEFSTRUCT copiers while trying to
hash out this ambiguity)?

We already have four equivalence predicates (EQ, EQL, EQUAL, EQUALP), but
they don't do all the things people want (or sometimes expect).  Many of us
in X3J13 believe that EQUAL was a big mistake in Lisp.  Trees of conses
generally represent some higher-level data structure, and it would probably
have been better to force programmers to define higher-level comparison
functions for them; EQUAL is generally a lazy solution.

It's too late to fix EQUAL.  But we didn't want to make the same mistake in
CLOS by adding a copier.

I did some design a couple of years ago on generic functions COPY-OBJECT
and EQUAL-OBJECT.  They solve the above shallow/deep issue by taking
parameters that indicate how to recurse.  In particular, there was a type
specifier parameter that indicated which types should be copied
recursively.  Type-specific keyword arguments could be passed in, which
could be used to further parametrize the way individual types are copied
(for instance, :LIST T indicates that conses should be copied with
COPY-LIST rather than COPY-TREE).

--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

ray@cme.nist.gov (Steve Ray) (11/28/90)

My understanding is that in general this is not a trivially solvable
problem. For example, what if an object has a slot which contains
another object? And what if that second object refers (directly or
indirectly) back to the first? How should you resolve such cycles, in
order to avoid infinite recursion, in a general fashion. Back in the
old days of Flavors, I remember using the :fasd-init option to tell an
object which slots to write out, which is one way of getting around
this. If there is some elegant way around this, I'd like to know too!
--

			Steven R. Ray
			National Institute of Standards and Technology
			Building 220, Room A127
			Gaithersburg, MD 20899

			ray@cme.nist.gov
			(301) 975-3524