(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).