Coming from a functional programming background, I sometimes miss referential transparency when knocking up prototypes in Lisp. For example, in Haskell I could write:
data Point = Point{ x :: Int, y :: Int } deriving (Show)
nullPoint = Point{ x = 0, y = 0 }
nextXPoint :: Point -> Point
nextXPoint p@Point{ x = x0 } = p{ x = x0 + 1 } -- automatically create copy of p
Main> nextXPoint nullPoint
Point{x=1,y=0}
Main> nullPoint
Point{x=0,y=0}
Main>
Behind the scenes, nextXPoint creates a shallow copy of its
parameter, with adjusted field values.
In Lisp, I would need to do the copying myself, and there starts the
trouble: (defstruct foo ...) automatically creates a
function copy-foo, but defclass does not.
So, when using CLOS I
even need to write copying functions for every object myself. Quite
unsatisfactory.
Fortunately, the CMU AI repository comes to the rescue with copy-objects.lisp. It even provides shallow and deep copying functions.
Unfortunately, the implementation is quite dated (1992), and so it does not run out of the box, at least not on SBCL. Kicking it a little seems to work, but I haven't tested more thoroughly yet.
--- copy_obj.cl.1 1995-06-10 01:06:43.000000000 +0200
+++ copy_obj.cl 2005-08-26 14:56:04.000000000 +0200
@@ -21,7 +21,20 @@
(in-package :ut)
-#+allegro
+;; hack
+(cl:defpackage "CLOS"
+ #+sbcl (:use "SB-MOP")
+ #-sbcl (:use "CLOSER-MOP")
+ (:export #:class-slots
+ #:slot-definition-allocation
+ #:slot-definition-name
+ #:metaobject))
+
+
+#+(or sbcl cmucl)
+(defun delete-all (set1 set2)
+ (set-difference set2 set1))
+
+#+(or allegro sbcl cmucl)
(eval-when (:compile-toplevel :load-toplevel :execute)
(export '(instance-slot-names
make-uninitialized-instance
@@ -30,7 +43,7 @@
shallow-copy
deep-copy)))
-#-allegro
+#-(or allegro sbcl cmucl)
(eval-when (compile load eval)
(export '(instance-slot-names
make-uninitialized-instance
@@ -65,7 +78,7 @@
(defmethod copy (object &key &allow-other-keys)
(deep-copy object))
-#-lucid
+#-(or sbcl lucid)
;; class metobject is not supplied by lucid clos
(defmethod uninitialized-copy ((object clos:metaobject) &key &allow-other-keys)
;; metaobjects are not copied
--- copy_obj.cl.1 1995-06-10 01:06:43.000000000 +0200
+++ copy_obj.cl 2005-08-26 14:56:04.000000000 +0200
@@ -21,7 +21,20 @@
(in-package :ut)
UPDATE 2008-07-22: Cut-Down Shallow Copy
A cut-down version which produces shallow copies only, can be found here: copy-instance.lisp
