<div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div style=""><div><span class="q"><blockquote type="cite"><br>only 3 mails, but in summary: there's a generic copy-thing protocol which is a one-fits-all copy protocol. but one could easily build some macrology on top of it for customized copy protocols that are the extension/customizations of the generic copy-thing protocol and/or other copy protocols. 
<br></blockquote><div><br></div></span><div>Hm, of course I like it when people find uses for ContextL. However, wouldn't a separation into different copy functions be sufficient here? (So, having separate functions like deep-copy, shallow-copy, structure-copy, and so on?)
</div><div><br></div><div>Note: I don't enough about metacopy, so it's very likely that I am missing something here.</div></div></div></blockquote><div><br><br>after some fighting with packages and asdf stuff here's what i came up with:
<br><br>(progn<br>  (define-copy-protocol adder-copy)<br>  (define-copy-protocol subber-copy)<br>  (define-copy-protocol list-element-duplicating-copy)<br>  (define-copy-protocol adder-and-list-element-duplicating-copy (adder-copy list-element-duplicating-copy))
<br><br>  (define-copy-method (copy-one adder-copy) ((n number) ht)<br>    (1+ n))<br><br>  (define-copy-method (copy-one subber-copy) ((n number) ht)<br>    (1- n))<br><br>  (define-copy-method (copy-one list-element-duplicating-copy) ((list cons) ht)
<br>    (mapcan (lambda (el)<br>              (list (copy-thing el) (copy-thing el)))<br>            list))<br>  <br>  (deftestsuite contextual (metacopy-test)<br>    ()<br>    (:test ((ensure-same (adder-copy '(1 2)) '(2 3) :test #'equal)))
<br>    (:test ((ensure-same (subber-copy '(2 3)) '(1 2) :test #'equal)))<br>    (:test ((ensure-same (list-element-duplicating-copy '(2 3)) '(2 2 3 3) :test #'equal)))<br>    (:test ((ensure-same (adder-and-list-element-duplicating-copy '(2 3)) '(3 3 4 4) :test #'equal)))))
<br> </div>unfortunately the packaging took about 10 times the effort to do then the copy-protocol code. the trick is to load the metacopy code twice into two different packages, one is called metacopy-with-contextl. this way defgeneric and define-layered-function can live happily next to each other and everyone can chose between the contextl based, and therefore more heavyweight, stuff or the old defmethod way.
<br><br>i had to patch slime, asdf, and asdf-system-connections to make it work... one problem is left though: the way i'm using asdf is either illegal or there's some bug in asdf, because contextl and some other packages are reloaded even though they are not changed since i've last generated my sbcl core. it does not cause any problems, but...
<br><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div style=""><div><span class="q"></span><div>Making ContextL optional is not straightforward because ContextL requires generic functions to be of the right metaclass, 
i.e., layered-function. In principle, CLOS specifices that you can change the metaclass of a generic function via change-class, but I am aware of only one CL implementation that actually implements this (that would be clisp), and I have doubts that this is a good idea in the first place.
</div><div><br></div><div>One idea would be to have a common entry point, roughly like this:</div><div><br></div><div>(defun copy (&rest args)</div><div>  (declare (dynamic-extent args))</div><div>  #+layered-copy (apply #'layered-copy args)
</div><div>  #-layered-copy (apply #'generic-copy args))</div></div></div></blockquote><div><br>this is the integration part:<br><br>(in-package #.(metacopy-system:metacopy-package))<br><br>#+with-contextl<br>(progn<br><br>
  (defparameter *copy-protocols* nil "Holds a list of copy protocol names")<br><br>  (defun calculate-layer-name-from-protocol-name (name)<br>    (intern (concatenate 'string "%CPL-" (string name))))<br>
<br>  (defmacro define-copy-protocol (name &optional super-protocols &rest options)<br>    "Define a copy protocol, which directly maps to a ContextL layer."<br>    `(progn<br>      (pushnew ',name *copy-protocols*)
<br>      (deflayer ,(calculate-layer-name-from-protocol-name name)<br>          ,(mapcar #'calculate-layer-name-from-protocol-name super-protocols)<br>        ,@options)<br>      (defun ,name (thing)<br>        (with-copy-protocol ,name
<br>          (copy-thing thing)))))<br><br>  (defmacro define-copy-function (name args &rest options)<br>    "A defgeneric, with or without contextl."<br>    `(define-layered-function ,name ,args<br>      ,@options))
<br><br>  (defmacro define-copy-method (name &rest body)<br>    "A defmethod, with or without contextl."<br>    (let ((protocol)<br>          (qualifiers)<br>          (args))<br>      (when (consp name)<br>
        (assert (= (length name) 2))<br>        (setf protocol (calculate-layer-name-from-protocol-name (second name)))<br>        (setf name (first name)))<br>      (loop for el :in body<br>            until (consp el) do
<br>            (push (pop body) qualifiers))<br>      (setf args (pop body))<br>      `(define-layered-method ,name ,@(when protocol `(:in-layer ,protocol)) ,@qualifiers ,args ,@body)))<br><br>  (defmacro with-copy-protocol (name &body body)
<br>    (setf name (calculate-layer-name-from-protocol-name name))<br>    `(with-active-layers (,name)<br>      ,@body)))<br><br>#-with-contextl<br>(progn<br><br>  (defmacro define-copy-function (name args &rest options)
<br>    "A defgeneric, with or without contextl."<br>    `(defgeneric ,name ,args<br>      ,@options))<br><br>  (defmacro define-copy-method (name args &rest options)<br>    "A defmethod, with or without contextl."
<br>    (assert (not (consp name)) (name) "You can only define layered copy-methods with the metacopy-with-contextl package")<br>    `(defmethod ,name ,args<br>      ,@options)))<br><br>Gary, i hope you'll like it and help tailor out the asdf glitches (i forward some methods from one system to another after rebinding a variable without too deep asdf internals knowledge). i'll play a bit more with this and send you the patches, but it'll take some time until all the patches get into the repos. if you want to play with this before that just drop me a mail and i'll attach them all.
<br><br></div></div>-- <br>- attila<br><br>"- The truth is that I've been too considerate, and so became unintentionally cruel...<br> - I understand.<br> - No, you don't understand! We don't speak the same language!"
<br>(Ingmar Bergman - Smultronstället)