From: ···············@gmail.com
Subject: how do i clone in CLOS?
Date: 
Message-ID: <2b13266f-f870-4943-94e7-a726774ec657@p25g2000hsf.googlegroups.com>
Actually, i want to make several instances of a subclass of the
object's class (with same values as the object).  Do I have to copy
the slots manually?

From: Ken Tilton
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <47bc7d28$0$25041$607ed4bc@cv.net>
···············@gmail.com wrote:
> Actually, i want to make several instances of a subclass of the
> object's class (with same values as the object).  Do I have to copy
> the slots manually?

Funny, Paul Graham had the same question. :)

Yep:

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

Your MOP may vary in the deets.

hth, kenny

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: ···············@gmail.com
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <fc995c2e-a5ed-459f-bd5c-1f22db028fc1@q78g2000hsh.googlegroups.com>
Thanks!

Nice code :)

Andrew

On Feb 20, 8:19 pm, Ken Tilton <···········@optonline.net> wrote:
> ···············@gmail.com wrote:
> > Actually, i want to make several instances of a subclass of the
> > object's class (with same values as the object).  Do I have to copy
> > the slots manually?
>
> Funny, Paul Graham had the same question. :)
>
> Yep:
>
> (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)))
>
> Your MOP may vary in the deets.
>
> hth, kenny
>
> --http://smuglispweeny.blogspot.com/http://www.theoryyalgebra.com/
>
> "In the morning, hear the Way;
>   in the evening, die content!"
>                      -- Confucius
From: Ken Tilton
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <47bc8d65$0$25039$607ed4bc@cv.net>
···············@gmail.com wrote:
> Thanks!
> 
> Nice code :)

Actually a collaborative effort by various Arc welders.

kenny

> 
> Andrew
> 
> On Feb 20, 8:19 pm, Ken Tilton <···········@optonline.net> wrote:
> 
>>···············@gmail.com wrote:
>>
>>>Actually, i want to make several instances of a subclass of the
>>>object's class (with same values as the object).  Do I have to copy
>>>the slots manually?
>>
>>Funny, Paul Graham had the same question. :)
>>
>>Yep:
>>
>>(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)))
>>
>>Your MOP may vary in the deets.
>>
>>hth, kenny
>>
>>--http://smuglispweeny.blogspot.com/http://www.theoryyalgebra.com/
>>
>>"In the morning, hear the Way;
>>  in the evening, die content!"
>>                     -- Confucius
> 
> 

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Kent M Pitman
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <ubq6b6wni.fsf@nhplace.com>
Ken Tilton <···········@optonline.net> writes:

> ···············@gmail.com wrote:
> > Actually, i want to make several instances of a subclass of the
> > object's class (with same values as the object).  Do I have to copy
> > the slots manually?
> 
> Funny, Paul Graham had the same question. :)
> 
> Yep:
> 
> (defun copy-instance (i)

But see also 

 http://www.nhplace.com/kent/PS/EQUAL.html

and keep in mind that copying has the same problem as equality.
From: Ken Tilton
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <47bcc9ab$0$25053$607ed4bc@cv.net>
Kent M Pitman wrote:
> Ken Tilton <···········@optonline.net> writes:
> 
> 
>>···············@gmail.com wrote:
>>
>>>Actually, i want to make several instances of a subclass of the
>>>object's class (with same values as the object).  Do I have to copy
>>>the slots manually?
>>
>>Funny, Paul Graham had the same question. :)
>>
>>Yep:
>>
>>(defun copy-instance (i)
> 
> 
> But see also 
> 
>  http://www.nhplace.com/kent/PS/EQUAL.html
> 
> and keep in mind that copying has the same problem as equality.

Keep in mind the OP's functional requirements document. :)

Would anything other than the shallow copy I suggested have "the same 
values as the object"?

This is good, you now have to figure out the entries "same" and "value" 
in your CLHS. :)

MWUAHAHAHHAHAHAHA!

kenny

ps. Just killing time till AI comes on. It's ladies night!

pps. When is Edi going to swing by and accuse me of shilling for Fox? 
He's overdur. We should check on him, make sure he is OK.

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Edi Weitz
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <uodaat6n4.fsf@agharta.de>
On Wed, 20 Feb 2008 19:47:03 -0500, Ken Tilton <···········@optonline.net> wrote:

> pps. When is Edi going to swing by and accuse me of shilling for
> Fox?  He's overdur. We should check on him, make sure he is OK.

I didn't even know that American Idol was broadcasted by Fox.  But the
real reason I was away is that I had to watch the Champions League
last night.  No worries, it's all good.

Gotta go now, UEFA Cup tonight...

-- 

European Common Lisp Meeting, Amsterdam, April 19/20, 2008

  http://weitz.de/eclm2008/

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Ken Tilton
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <47bdf2e9$0$25042$607ed4bc@cv.net>
Edi Weitz wrote:
> On Wed, 20 Feb 2008 19:47:03 -0500, Ken Tilton <···········@optonline.net> wrote:
> 
> 
>>pps. When is Edi going to swing by and accuse me of shilling for
>>Fox?  He's overdur. We should check on him, make sure he is OK.
> 
> 
> I didn't even know that American Idol was broadcasted by Fox.  But the
> real reason I was away is that I had to watch the Champions League
> last night.  No worries, it's all good.
> 
> Gotta go now, UEFA Cup tonight...
> 

Damn, I'm stuck adding data integrity to Triple Cells for my ECLM 2008 
talk. Just hope I get to it before the yobbos storm the stage.

kenny

ps. AI result night tonight! I am beside myselves! k

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <rem-2008mar02-003@yahoo.com>
> Ken Tilton <···········@optonline.net>
> .... When is Edi going to swing by and accuse me of shilling for Fox?
> From: Edi Weitz <········@agharta.de>
> I didn't even know that American Idol was broadcasted by Fox.

OT: Why would anybody want to watch a dumb program like AI?
The only program worth watching on Fox is "Dead like Me" (Saturday 4PM).
Life sucks, then you die, then afterlife sucks even worse than life did!
From: Steven M. Haflich
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <47C9CA51.2000005@alum.mit.edu>
Kent M Pitman wrote:
> But see also 
> 
>  http://www.nhplace.com/kent/PS/EQUAL.html
> 
> and keep in mind that copying has the same problem as equality.

I agree with this issue, of course, but the issues run both deeper and 
wider.

While ignoring the meaning of `same' within the context of any 
particular metaclass, it may not be possible to preserve class semantics 
under copying of standard-objects even within the ANS defined metaclasses:

   cl-user(43): (defmethod foo ((x integer)) (1+ x))
   #<standard-method foo (integer)>
   cl-user(44): (typep #'foo 'standard-object)
   t
   cl-user(45): (funcall (copy-instance #'foo) 22/7)
   Error: Attempt to funcall a generic-function without first
          initializing its lambda-list.  Number of required arguments
          cannot be determined.

I believe this error is conformant with the ANS.

The underlying issue here is, as Kent implies, that "clone" (or equal) 
is not well defined within a language as powerful as CL.  So if you have 
in mind a particular notion of "clone" you need to implement it 
yourself, realizing that it might violate the assumption of other 
portable classes you might have running in your Lisp world.  But they 
won't call clone, since the concept is not well defined within a 
language as powerful as CL therefore no reasonable application needs 
such an inadequately-defined general clone function.
From: Leslie P. Polzer
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <f359c1c9-3a53-4b41-a320-62597d55d416@e60g2000hsh.googlegroups.com>
On Feb 20, 8:19 pm, Ken Tilton <···········@optonline.net> wrote:

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

sd, sn, c, i... Arc really must have made an impression on you.
Or do you have a secret love for C, by any chance?

  SCNR
From: Ken Tilton
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <47bdf6d1$0$25055$607ed4bc@cv.net>
Leslie P. Polzer wrote:
> On Feb 20, 8:19 pm, Ken Tilton <···········@optonline.net> wrote:
> 
> 
>>(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)))
> 
>                    -- Confucius
> 
> sd, sn, c, i... Arc really must have made an impression on you.

I gather you have not seen my Cells code.

> Or do you have a secret love for C, by any chance?

The length of a dataname should be proportional to the line count of its 
lexical range and the algorithmic complexity within that range. The more 
astute amongst you will realize I erred on the side of loquacity with 
the two-character names.

pg seems to agree, he comes up with an effective length of zero for the 
parameter name length of a one parameter anonymous function. He uses _.

kenny

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <rem-2008mar02-004@yahoo.com>
> From: Ken Tilton <···········@optonline.net>
> The length of a dataname should be proportional to the line count
> of its lexical range and the algorithmic complexity within that
> range.

As a general principle, I like your suggestion. Maybe I should try
to apply it in my own code more than I already do implicitly. Or
maybe I already have an optimal compromise between your principle
and the opposing principle of self-documenting code.

For integers, I use 'i' or 'n', except if it's an index into a
sequence in which case I use 'ix'. For strings, streams, and
general sequences, respectively, I use: str, strm, seq.
When I parse a string into many pieces using LOCATION, I typically
use ix0 for very start of current scan, ix1,2,3,... for successive
positions that define boundaries of parts, and ix9 for the final
index of this scan which will be ix0 next time around.
Since global scope is larger than any lexical scope, I use totally
verbose names to virtually self-document the input and process and
output of each defined function.  For example, in processing RFC822 e-mail:
allhdrs-to-subj-patches  takes a list of all headers and produces a patch list
                          for whereever the Subject: key appears.
varbigstr+strstr+onepat-write  takes an uninterned symbol bound to a big string,
                                and an output string stream, and a single
                                patch record, and writes the output to the string
string+patches-perform  takes a string, and a list of patches, and performs
                         those patches upon the string to yield a new string
varwholemsg-get-uidl takes an uninterned symbol bound to a big string which is
                      an entire message (header+body), and searches for the
                      line that says X-UIDL: and returns the associated value
Why do I pass these uninterned symbols instead of the string itself?
Because I'm using a VT100 dialup without any flow control, and if an ERROR
should be signalled from within such a function then the BREAK generated
by the ERROR will spew out the very long string for ten or fifteen minutes
with no way to stop the Unix and modem buffers from filling up and
scrolling the VT100 emulator all the way to one complete pass through
all the buffer causing the error message to be permanently lost from the
emulator. Best to just have it print the *NAME* of the uninterned symbol,
which is something like S385472 for a string of length 385472 characters,
then get on with seeing what the rest of the parameters are and
what might have gone wrong in my new code I'm developing. Below is
my utility for making those very useful uninterned symbols:

;Given a string or list, make an uninterned symbol like GENSYM,
; except have the name indicate the length.
;If given another object, use TYPE-OF it as name.
;Then bind that symbol to the original given value to "hide" that value
; so that printing the symbol doesn't spew out unstoppably for ten minutes.
(defun lensym-bind (val)
  (prog (nam sym)
    (setq nam
      (cond ((stringp val) (format nil "S~D" (length val)))
            ((listp val) (format nil "L~D" (length val)))
            (t (format nil "~A" (type-of val)))))
    (setq sym (make-symbol nam))
    (type-of (set sym val))
    (return sym)
    ))
;Yeah, I use PROG all over the place, handier than LET* for line-at-a-time
; debugging by copy&paste over VT100 dialup into Unix shell.


Oh, I forgot to say elsewhere in the thread, about John McCarthy's rebuke
against another programming language, and what's essential about LIsp:
Every executable expression in Lisp is simultaneously:
- Procedural (you can put it in a sequence such as PROG or PROGN)
- Functional (it can be used in a place where a return value is required)
This is for example different from that horrible language that K&R
produced where conditional statements and conditional expressions
must use a totally different syntax:
- if (x<5) then printf("short\n"); else printf("long\n");
- msg = (x<5) ? "short" : "long";
Or that much older language that defines SUBROUTINE and FUNCTION subprograms,
one of which can modify its parameters but not return a value, and the
other of which must return a value but can't modify its parameters,
and which must be called using somewhat different syntaxes:
- CALL MYSUBR(X,Y)
- Z = MYFUNC(X,Y)
(everything upper case on IBM 026 keypunch of course)

IMO the single kind of executable expression that can be used
everywhere is one of the big "programmer-friendly" aspects of Lisp.
You don't have to constantly remember which system-library
procedures are functions and which aren't and be careful to use
each kind only when appropriate. You don't have to remember two
different names or syntaxes for whether you do essentially the same
thing in a function or statement context. And a lot of functions do
*both* of side effects (on some passed structure) and returning a
useful value (or multiple values, which is even more useful), and
can be used for both or either at any time.
From: Leslie P. Polzer
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <22c0a361-291a-431d-9bc8-973915e1d834@f47g2000hsd.googlegroups.com>
On Feb 20, 8:19 pm, Ken Tilton <···········@optonline.net> wrote:

>        with c = (allocate-instance i-class)

Hrm, using ALLOCATE-INSTANCE instead of MAKE-INSTANCE might lead to
subtle problems. For example, it doesn't seem to work with the
Elephant MOP.

  Leslie
From: Ken Tilton
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <47bdf4ee$0$25049$607ed4bc@cv.net>
Leslie P. Polzer wrote:
> On Feb 20, 8:19 pm, Ken Tilton <···········@optonline.net> wrote:
> 
> 
>>       with c = (allocate-instance i-class)
> 
> 
> Hrm, using ALLOCATE-INSTANCE instead of MAKE-INSTANCE might lead to
> subtle problems. For example, it doesn't seem to work with the
> Elephant MOP.

Yeah, that was offered as a starting point to be debugged. The original 
was created cuz pg needed it, if he wanted something that worked I was 
going to charge him. Figured he had some loose change lying around.

I had started with make-instance cuz I did not want to bypass 
initialization, someone suggested allocate-instance and I started 
thinking, hmmm, we're copying something that has passed initialization, 
might be Deeply Wrong to go thru initialization. But your Elephant use 
case has me thinking I might have been right the first time. Or maybe 
thinking Elephant just needs special handling. (Cue Kent on copying.)

kenny

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: sross
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <2a8e5d3d-0220-4616-aaaf-cfa35cb5fac3@d5g2000hsc.googlegroups.com>
On Feb 21, 10:03 pm, Ken Tilton <···········@optonline.net> wrote:
> I had started with make-instance cuz I did not want to bypass
> initialization, someone suggested allocate-instance and I started
> thinking, hmmm, we're copying something that has passed initialization,
> might be Deeply Wrong to go thru initialization. But your Elephant use
> case has me thinking I might have been right the first time. Or maybe
> thinking Elephant just needs special handling. (Cue Kent on copying.)

I believe that was myself, and I think I'm going to make it clear that
I'm pretty
firmly in the `initialize-instance only runs once` camp.
For reinitialization we have reinitialize-instance, as Pascal pointed
out, and that the
issues that Elephant have regarding allocate-instance are more
accidental than by design.

Come to think of it how is a copied persistent-instance to behave and
just as importantly
how is it to behave in the presence of multiple threads? I know we
have an instictive idea
of what it is to do but implementing a comprehensive copy for a
persistent object is more
work than we'd like to admit, especially once methods like change-
class are taken into
consideration.

sean.

-
Now waiting for Kent to make him look like a fool.
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <rem-2008mar02-005@yahoo.com>
> From: sross <······@gmail.com>
> Come to think of it how is a copied persistent-instance to behave
> and just as importantly how is it to behave in the presence of
> multiple threads? I know we have an instictive idea of what it is
> to do but implementing a comprehensive copy for a persistent object
> is more work than we'd like to admit, especially once methods like
> change-class are taken into consideration.

Caveat: I'm not sure what you mean by "persistent" here. Normally
"persistent data" means the data survives not just the lexical
context and core-image of the application or interactive Lisp
environment but also survives logout from the ISP and system
restarts, just about everything except a hard-disk crash. Normally
persistent data is kept in disk files, or in records in tables in
databases in a RDBS backed by disk files. But here the term seems
to refer only to something that remains around during the whole
course of an interactive Lisp session. But I'm just curious as to
your meaning, because that adjective is irrelevant to my response
below:

It seems to me that the posted code earlier in this thread:
> (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)))
would need some kind of lock on the class that i is an instance of
at the moment class-of is called, to protect against another thread
re-defining the class in the middle of this code, which would cause
a mismatch between what mop:class-slots or mop:slot-definition-name
returns and the actual slots that exist in i-class hence in c at
the time (setf (slot-value c sn) ...) is executed.

I thought as I started composing this response that a lock would
also be needed on the object i also, in case that object got its
class membership changed in the middle of this code, but actually
now that I think more carefully that might not be needed. The
behaviour would be that the return value i.e. c is an instance of
whatever class i was at the moment (class-of i) was called, not
necessary the same class that object i has at the moment of return,
which isn't really a problem IMO. Once the local variable i-class
has been set to *any* class whatsoever, the rest of the code is all
consistent, regardless of any continuing relationship between i and
i-class. Returned c will be a valid instance of i-class.

So does CLOS or MOP support any lock on a CLOS object (in this case
a class object) that prevents it from being modified/redefined
during some critical section such as the above code? If so, the
above code would then be something like:

! (defun copy-instance (i)
!   (let ((i-class (class-of i)))
!     (with-lock (i-class :READ-ALLOWED T :MODIFY-ALLOWED NIL)
!       (loop
!        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)))))
Note my idea for WITH-LOCK would be that T means any process can do
it, NIL means no process not even *this* process can do it and
:SELF means other processes are locked out but this process can do
it neverthess, as parameters for the keywords :read-allowed and
:modify-allowed. For code that needed to modify an object, where
the object might be temporarily in an inconsistent state, the usual
values would be :READ-ALLOWED :SELF :MODIFY-ALLOWED :SELF to
protect against other threads seeing any inconsistent state.
Is something like WITH-LOCK already in CL+CLOS+MOP?
(Yeah, I know, threads aren't in ANSI CL at all, so locks aren't
 either, but I'm asking about de facto standards in common use since
 the ANSI standard, OK?)

P.S. I've just a pre-beginner at CLOS. Bill Gosper told me about
OOP and multiple inheritance etc. in the early-mid 1970s, so I had
some vague idea all this time, and I used a different version of
OOP in Macintosh Allegro Common Lisp circa 1990-98, and I picked up
tidbits about CLOS from this newsgroup in recent years, and in Java
there's no way to escape OOP, but this thread prompted me to look
for a tutorial on CLOS just today, whereupon I found
 <http://cl-cookbook.sourceforge.net/clos-tutorial/index.html>
which seems to be exactly what I needed to understand this thread,
and to get a clearer idea of CLOS in general. I hope my analysis
(above) of the need for one kind of lock but not the other is
essentially correct.

Maybe someday I'll actually find a good use for CLOS for my own code...
Too bad there isn't any free version of CL for Macintosh System 7.5.5
(PowerLisp is totally broken, and XLisp is semi-broken in a different way).
(My Mac Plus running System 6.0.3 and MACL 1.2.2 died in 1999.)
From: Pascal Costanza
Subject: Re: how do i clone in CLOS?
Date: 
Message-ID: <6263g5F21j3imU1@mid.individual.net>
Leslie P. Polzer wrote:
> On Feb 20, 8:19 pm, Ken Tilton <···········@optonline.net> wrote:
> 
>>        with c = (allocate-instance i-class)
> 
> Hrm, using ALLOCATE-INSTANCE instead of MAKE-INSTANCE might lead to
> subtle problems. For example, it doesn't seem to work with the
> Elephant MOP.

It may help to call reinitialize-instance (without any initargs) in the end.


Pascal

-- 
1st European Lisp Symposium (ELS'08)
http://prog.vub.ac.be/~pcostanza/els08/

My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/