Arc Forumnew | comments | leaders | submitlogin
CL Question
5 points by pg 5895 days ago | 5 comments
I'm trying to translate some CL code to Arc. Anyone know if there's a predefined function for doing a shallow copy of an instance?


4 points by kennytilton 5895 days ago | link

No, there is not. Only with defstructs do you get a copier. But with CLOS instances, unlike defstructs, you can use the MOP to iterate over the slots of an instance to do a rough simulation of copying. That code might have portability issues, but I think Pascal Costanza has a library out there somewhere that tries to account for MOP variations in CLs.

-----

4 points by kennytilton 5895 days ago | link

In AllegroCL:

  (defun copy-instance (i &aux (i-class (class-of i)))
   (let ((c (make-instance i-class)))
    (loop for s in (mop:class-slots i-class)
        do (setf (slot-value c (mop:slot-definition-name s))
             (slot-value i (mop:slot-definition-name s)))
          finally (return c))))
Where you see mop: look out. :) The MOP package of the CL implementation you are using may even be nicknamed CLOS. You may have to take the union of class-direct-slots and class-indirect-slots. The slot returned may be the slot name itself. Stuff like that.

-----

3 points by sross 5894 days ago | link

Although I would suggest using allocate-instance over make-instance and ensuring that

  (slot-boundp i (mop:slot-definition-name s))
is true before attempting to obtain the slot-value.

-----

3 points by kennytilton 5894 days ago | link

OK, that (and crankin the loop) would make it:

  (defun copy-instance (i)
     (loop with i-class = (class-of i)
      with c = (allocate-instance i-class)
      for sd in (mop:class-slots i-class)
      for sn = (mop:slot-definition-name sd)
      when (slot-boundp i sn)
      do (setf (slot-value c sn)
           (slot-value i sn))
      finally (return c)))

But what if necessary side-effects happen in initialize-instance? Though that could as easily make a case for allocate-instance, if Paul needs to avoid those side effects.

I think the bottom line is that I should have emphasized that copy-instance above might not survive first contact with the enemy (the functional requirements).

-----

1 point by lemonodor 5894 days ago | link

Are you asking for a function in CL or in Arc?

This is what I use in CL:

  (defun class-slots (class)
    #+(or digitool openmcl) (ccl:class-slots class)
    #+sbcl (sb-mop:class-slots class)
    #+cmu (mop:class-slots class)
    #+lispworks (clos:class-slots class)
    #+allegro (mop:class-slots class))

  (defun slot-definition-name (slot-defn)
    #+(or digitool openmcl) (ccl:slot-definition-name slot-defn)
    #+sbcl (sb-mop:slot-definition-name slot-defn)
    #+cmu (mop:slot-definition-name slot-defn)
    #+lispworks (clos:slot-definition-name slot-defn)
    #+allegro (mop:slot-definition-name slot-defn))

  (defmethod clone-object ((object T))
    (let ((copy (allocate-instance (class-of object))))
      (loop for slot in (class-slots (class-of object))
	   do (let ((slot-name (slot-definition-name slot)))
		(when (slot-boundp object slot-name)
		  (setf (slot-value copy slot-name)
			(slot-value object slot-name)))))
      copy))

-----