From: Madhu
Subject: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <m3vdu4dx1z.fsf@moon.robolove.meer.net>
(:I put `misguided' in the subject to catch Kenny's attention:)

The situation is not new.  One wishes to create a new object which is
slightly different from another object, i.e. where a few slots have
different values.  I found the sweetest syntax to do this was in CMU's
KR (when using Create-Instance during prototype creation).  In CLOS, I'd
like to use the MAKE-INSTANCE mechanism to do the defaulting like this:

	(MAKE-INSTANCE 'Class1 :defaults obj2 :slot1 val1 :slot2 val2)

should fill in SLOT1 and SLOT2 from this form and use all other initargs
from obj2 when creating an instance of Class1.  Here is an
implementation which uses an around method on iNITIALIZE-INSTANCE to
accomplish this.  For this to work CLASS1 would just need to subclass
the magic mixin class DEFAULT-COPYING-MIXIN.  This works for me in PCL
and under LW.  How correct is it?
--
Madhu


#+nil
(mapcar (lambda (x &aux (a (find-symbol x #+pcl :pcl #-pcl :clos)))
          (and a (import a)))
        '("CLASS-SLOTS" "SLOT-DEFINITION-INITARGS" "CLASS-DIRECT-SLOTS"
          "SLOT-DEFINITION-NAME"))


(defclass default-copying-mixin ()
  ()
  (:documentation "Magic class.  MAKE-INSTANCE on subclasses can supply
a :DEFAULT OBJ keyword argument to default slot values from that OBJ."))


(defmethod initialize-instance :around ((obj default-copying-mixin) &rest args
                                        &key default &allow-other-keys
                                        &aux initarg)
  (when default
    (setq args
          (nconc
           ;; snarf initargs from DEFAULT object
           (loop for slot in (class-direct-slots (class-of default))
                 for slot-name = (slot-definition-name slot)
                 when (and (slot-exists-p default slot-name)
                           (slot-boundp default slot-name)
                           (setq initarg (car (slot-definition-initargs slot))))
                 nconc (list initarg (slot-value default slot-name)))
           ;; frob args to remove the DEFAULT keyword arg
           (loop for prev = nil then cons for cons on args
                 when (eql (car cons) :default)
                 if (endp prev) return (cddr args)
                 else return (prog1 args (setf (cdr prev) (cddr cons)))))))
  (apply #'call-next-method obj args))

From: Kenny
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <49340614$0$14321$607ed4bc@cv.net>
Madhu wrote:
> (:I put `misguided' in the subject to catch Kenny's attention:)

No need, I was delighted to see someone talking about Lisp instead of 
Qi, Clojure, Ruby, F#, and Javascript.

> 
> The situation is not new.  One wishes to create a new object which is
> slightly different from another object, i.e. where a few slots have
> different values.  I found the sweetest syntax to do this was in CMU's
> KR (when using Create-Instance during prototype creation). 

Wouldn't that be because KR was (or lived atop) a prototype-based form 
of OO? :)

Just wondering, in a non-protoype OO model, when does this ever come up?

peace,k


  In CLOS, I'd
> like to use the MAKE-INSTANCE mechanism to do the defaulting like this:
> 
> 	(MAKE-INSTANCE 'Class1 :defaults obj2 :slot1 val1 :slot2 val2)
> 
> should fill in SLOT1 and SLOT2 from this form and use all other initargs
> from obj2 when creating an instance of Class1.  Here is an
> implementation which uses an around method on iNITIALIZE-INSTANCE to
> accomplish this.  For this to work CLASS1 would just need to subclass
> the magic mixin class DEFAULT-COPYING-MIXIN.  This works for me in PCL
> and under LW.  How correct is it?
> --
> Madhu
> 
> 
> #+nil
> (mapcar (lambda (x &aux (a (find-symbol x #+pcl :pcl #-pcl :clos)))
>           (and a (import a)))
>         '("CLASS-SLOTS" "SLOT-DEFINITION-INITARGS" "CLASS-DIRECT-SLOTS"
>           "SLOT-DEFINITION-NAME"))
> 
> 
> (defclass default-copying-mixin ()
>   ()
>   (:documentation "Magic class.  MAKE-INSTANCE on subclasses can supply
> a :DEFAULT OBJ keyword argument to default slot values from that OBJ."))
> 
> 
> (defmethod initialize-instance :around ((obj default-copying-mixin) &rest args
>                                         &key default &allow-other-keys
>                                         &aux initarg)
>   (when default
>     (setq args
>           (nconc
>            ;; snarf initargs from DEFAULT object
>            (loop for slot in (class-direct-slots (class-of default))
>                  for slot-name = (slot-definition-name slot)
>                  when (and (slot-exists-p default slot-name)
>                            (slot-boundp default slot-name)
>                            (setq initarg (car (slot-definition-initargs slot))))
>                  nconc (list initarg (slot-value default slot-name)))
>            ;; frob args to remove the DEFAULT keyword arg
>            (loop for prev = nil then cons for cons on args
>                  when (eql (car cons) :default)
>                  if (endp prev) return (cddr args)
>                  else return (prog1 args (setf (cdr prev) (cddr cons)))))))
>   (apply #'call-next-method obj args))
From: Madhu
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <m37i6jdzf2.fsf@moon.robolove.meer.net>
* Kenny <·························@cv.net> :
Wrote on Mon, 01 Dec 2008 10:43:16 -0500:

|> The situation is not new.  One wishes to create a new object which is
|> slightly different from another object, i.e. where a few slots have
|> different values.  I found the sweetest syntax to do this was in
|> CMU's KR (when using Create-Instance during prototype creation).
|
| Wouldn't that be because KR was (or lived atop) a prototype-based form
| of OO? :)
|
| Just wondering, in a non-protoype OO model, when does this ever come
| up?

One example might be if you represent the state of some computation as
CLOS objects --- and you are doing say search.  Each branch [of the
search tree] would make a copy of the state after making a variation on
that state at the branch point.  [A common variation of this theme is
when you are coding up some off the shelf algorithm which happens to be
expressed in "a functional way"]

Another simplistic sketch might be say you have a `date' class (with
slots for year minute etc) and are displaying the positions of planets
in the solar system on particular date x with (display-chart x).
Now you want to show in a new window, the positions for a different year
but same date.  So you'd use
 (display-chart (make-instance 'date :year 1977 :defaults x))

This may be especially useful if you are doing this interactively.  Not
sure how convincing this is :)
--
Madhu
From: Kenny
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <4934b499$0$14291$607ed4bc@cv.net>
Madhu wrote:
> * Kenny <·························@cv.net> :
> Wrote on Mon, 01 Dec 2008 10:43:16 -0500:
> 
> |> The situation is not new.  One wishes to create a new object which is
> |> slightly different from another object, i.e. where a few slots have
> |> different values.  I found the sweetest syntax to do this was in
> |> CMU's KR (when using Create-Instance during prototype creation).
> |
> | Wouldn't that be because KR was (or lived atop) a prototype-based form
> | of OO? :)
> |
> | Just wondering, in a non-protoype OO model, when does this ever come
> | up?
> 
> One example might be if you represent the state of some computation as
> CLOS objects --- and you are doing say search.  Each branch [of the
> search tree] would make a copy of the state after making a variation on
> that state at the branch point.  [A common variation of this theme is
> when you are coding up some off the shelf algorithm which happens to be
> expressed in "a functional way"]

If Deep Blue had copied CLOS instances to search move space Kasparov's 
Mom could have given it a Queen. Not even Pascal would use CLOS 
instances for this, and he'll use them for anything.

> 
> Another simplistic sketch might be say you have a `date' class (with
> slots for year minute etc) and are displaying the positions of planets
> in the solar system on particular date x with (display-chart x).
> Now you want to show in a new window, the positions for a different year
> but same date.  So you'd use
>  (display-chart (make-instance 'date :year 1977 :defaults x))

You are representing a date with a CLOS instance? Oh, my.

I was thinking:

   (display-chart (+ x (* 365 24 3600 year-delta)))

Leap year left as an exercies.

> 
> This may be especially useful if you are doing this interactively.  Not
> sure how convincing this is :)

I do believe you just expressed a self-deciding uncertainty. Not sure we 
have had one of those before. Sweet!

Unfortunately, the fact that you are inventing possible use cases proves 
my point: you have no use case arising from your working code, you were 
just tool-fantasizing. Now where did I leave that beach rant...?


hth,kxo
From: Kenny
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <49352cc9$0$20301$607ed4bc@cv.net>
Madhu wrote:
> * Kenny <·························@cv.net> :
> Wrote on Mon, 01 Dec 2008 23:07:53 -0500:
> 
> |> Another simplistic sketch might be say you have a `date' class (with
> |> slots for year minute etc) and are displaying the positions of
> |> planets in the solar system on particular date x with (display-chart
> |> x).  Now you want to show in a new window, the positions for a
> |> different year but same date.  So you'd use
> |>  (display-chart (make-instance 'date :year 1977 :defaults x))
> |
> | You are representing a date with a CLOS instance? Oh, my.
> |
> | I was thinking:
> |
> |   (display-chart (+ x (* 365 24 3600 year-delta)))
> 
> muahahahaa
> why? 

Because (type-of (get-universal-time)) -> fixnum?

> because javascript doesn't have keywords?

Nonsense, the buttheads just put the colon on the wrong end:

   {year: 2009 month: 1 day: 20}

> 
> muahahahaha
> 
> |> This may be especially useful if you are doing this interactively.  Not
> |> sure how convincing this is :)
> |
> | I do believe you just expressed a self-deciding uncertainty. Not sure
> | we have had one of those before. Sweet!
> 
> not sure what or how much that means :)

It means you would not have said that had you found it convincing.

> 
> | Unfortunately, the fact that you are inventing possible use cases
> | proves my point: you have no use case arising from your working code,
> | you were just tool-fantasizing. Now where did I leave that beach
> | rant...?
> 
> Painting the toolshed beats dealing with the harder problems that the
> app at hand youre writing presents!  Surely you knew that!  

I believe anyone who has tested a paint color on a different surface 
under different lighting conditions than the thing one actually intends 
to paint would like a word with you about the value of this argument by 
analogy.

:)

kzo
From: Madhu
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <m3r64qm3q2.fsf@moon.robolove.meer.net>
[last post in this thread]

* Kenny <·························@cv.net> :
Wrote on Tue, 02 Dec 2008 07:40:41 -0500:

| Madhu wrote:
|> * Kenny <·························@cv.net> :
|> Wrote on Mon, 01 Dec 2008 23:07:53 -0500:
|>
|> |> Another simplistic sketch might be say you have a `date' class (with
|> |> slots for year minute etc) and are displaying the positions of
|> |> planets in the solar system on particular date x with (display-chart
|> |> x).  Now you want to show in a new window, the positions for a
|> |> different year but same date.  So you'd use
|> |>  (display-chart (make-instance 'date :year 1977 :defaults x))
|> |
|> | You are representing a date with a CLOS instance? Oh, my.
|> |
|> | I was thinking:
|> |
|> |   (display-chart (+ x (* 365 24 3600 year-delta)))
|>
|> muahahahaa
|> why? 
|
| Because (type-of (get-universal-time)) -> fixnum?

[snip]

|> |> This may be especially useful if you are doing this interactively.
|> |> Not sure how convincing this is :)
|> |
|> | I do believe you just expressed a self-deciding uncertainty. Not sure
|> | we have had one of those before. Sweet!
|>
|> not sure what or how much that means :)
|
| It means you would not have said that had you found it convincing.

No, it was not a question of my conviction, but of whether I'd be able
to convince you or rather if I could get you to admit you were
convinced.  I was afraid you'd instead employ some sophist debating
tactic, and you did --- in this case you used the fact that a problem
can be solved in many different ways.  

The examples I gave were to illustrate how this technique would be
useful WHEN YOU USED CLOS OBJECTS.  Your reponse to that on both cases
has been is "this is NOT USEFUL BECAUSE I can solve this problem without
using CLOS OBJECTS", well duh!

|> | Unfortunately, the fact that you are inventing possible use cases
|> | proves my point: you have no use case arising from your working code,
|> | you were just tool-fantasizing. Now where did I leave that beach
|> | rant...?
|>
|> Painting the toolshed beats dealing with the harder problems that the
|> app at hand youre writing presents!  Surely you knew that!  
|
| I believe anyone who has tested a paint color on a different surface
| under different lighting conditions than the thing one actually
| intends to paint would like a word with you about the value of this
| argument by analogy.

I couldn't come up with a better non-sequitur!


--
Madhu
From: Kenny
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <4935ec12$0$20302$607ed4bc@cv.net>
> |> | Unfortunately, the fact that you are inventing possible use cases
> |> | proves my point: you have no use case arising from your working code,
> |> | you were just tool-fantasizing. Now where did I leave that beach
> |> | rant...?
> |>
> |> Painting the toolshed beats dealing with the harder problems that the
> |> app at hand youre writing presents!  Surely you knew that!  
> |
> | I believe anyone who has tested a paint color on a different surface
> | under different lighting conditions than the thing one actually
> | intends to paint would like a word with you about the value of this
> | argument by analogy.
> 
> I couldn't come up with a better non-sequitur!

I feel a House coming on, or maybe some bloggery. In brief, there are 
times when distillation to a minimal case rocks, usually when faced with 
a bug cuz as long as the bug still happens one has not changed the 
subject. Otherwise, you generally end up with people working on an 
unrelated problem, which is why argument by analogy is so useless.

Meanwhile, Pascal reminded me of the wild CLOS copying code I did write 
once. What was the requirement? I had to copy CLOS instances. Literally, 
that was all I had to do. MWUAGAHAHAHAHAHAHAHAHAHAHAHAHAHAHA.

It was a DB partial-replication scheme where AllegoStore (persistent 
CLOS) was the DB. And it turned out beautifully that we did want to copy 
only those slots that had been authored at make-instance time and let 
other slots pick up their values (if unauthored at m/i time) from the 
class defintion.

Because classes change and in our case we very much wanted those changed 
reflected in new instances. How scary is that? Persistent cells were 
involved, too. Woohoo!

IIRC, I hit the problem over the head, storing somewhere in the instance 
the slot-names authored, then did what you did with the initargs/values.

hth,kzo
From: ··················@gmail.com
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <9d9bac9d-61af-49f9-b7f2-740fe4f202de@c1g2000yqg.googlegroups.com>
On Dec 2, 9:16 pm, Kenny <·········@gmail.com> wrote:
> > |> | Unfortunately, the fact that you are inventing possible use cases
> > |> | proves my point: you have no use case arising from your working code,
> > |> | you were just tool-fantasizing. Now where did I leave that beach
> > |> | rant...?
> > |>
> > |> Painting the toolshed beats dealing with the harder problems that the
> > |> app at hand youre writing presents!  Surely you knew that!  
> > |
> > | I believe anyone who has tested a paint color on a different surface
> > | under different lighting conditions than the thing one actually
> > | intends to paint would like a word with you about the value of this
> > | argument by analogy.
>
> > I couldn't come up with a better non-sequitur!
>
> I feel a House coming on, or maybe some bloggery. In brief, there are
> times when distillation to a minimal case rocks, usually when faced with
> a bug cuz as long as the bug still happens one has not changed the
> subject. Otherwise, you generally end up with people working on an
> unrelated problem, which is why argument by analogy is so useless.
>
> Meanwhile, Pascal reminded me of the wild CLOS copying code I did write
> once. What was the requirement? I had to copy CLOS instances. Literally,
> that was all I had to do. MWUAGAHAHAHAHAHAHAHAHAHAHAHAHAHAHA.
>
> It was a DB partial-replication scheme where AllegoStore (persistent
> CLOS) was the DB. And it turned out beautifully that we did want to copy
> only those slots that had been authored at make-instance time and let
> other slots pick up their values (if unauthored at m/i time) from the
> class defintion.
>
> Because classes change and in our case we very much wanted those changed
> reflected in new instances. How scary is that? Persistent cells were
> involved, too. Woohoo!
>
> IIRC, I hit the problem over the head, storing somewhere in the instance
> the slot-names authored, then did what you did with the initargs/values.
>
> hth,kzo

The important part of it isn't really the ability to copy the CLOS
objects, it is the ability to mutate them.
This would certainly have application in various stochastic approaches
(the object representing the state of a system).

(Although for implementation I would probably rather write a macro to
do the make-instance...)
From: Kenny
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <49360d46$0$14312$607ed4bc@cv.net>
··················@gmail.com wrote:
> On Dec 2, 9:16 pm, Kenny <·········@gmail.com> wrote:
> 
>>>|> | Unfortunately, the fact that you are inventing possible use cases
>>>|> | proves my point: you have no use case arising from your working code,
>>>|> | you were just tool-fantasizing. Now where did I leave that beach
>>>|> | rant...?
>>>|>
>>>|> Painting the toolshed beats dealing with the harder problems that the
>>>|> app at hand youre writing presents!  Surely you knew that!  
>>>|
>>>| I believe anyone who has tested a paint color on a different surface
>>>| under different lighting conditions than the thing one actually
>>>| intends to paint would like a word with you about the value of this
>>>| argument by analogy.
>>
>>>I couldn't come up with a better non-sequitur!
>>
>>I feel a House coming on, or maybe some bloggery. In brief, there are
>>times when distillation to a minimal case rocks, usually when faced with
>>a bug cuz as long as the bug still happens one has not changed the
>>subject. Otherwise, you generally end up with people working on an
>>unrelated problem, which is why argument by analogy is so useless.
>>
>>Meanwhile, Pascal reminded me of the wild CLOS copying code I did write
>>once. What was the requirement? I had to copy CLOS instances. Literally,
>>that was all I had to do. MWUAGAHAHAHAHAHAHAHAHAHAHAHAHAHAHA.
>>
>>It was a DB partial-replication scheme where AllegoStore (persistent
>>CLOS) was the DB. And it turned out beautifully that we did want to copy
>>only those slots that had been authored at make-instance time and let
>>other slots pick up their values (if unauthored at m/i time) from the
>>class defintion.
>>
>>Because classes change and in our case we very much wanted those changed
>>reflected in new instances. How scary is that? Persistent cells were
>>involved, too. Woohoo!
>>
>>IIRC, I hit the problem over the head, storing somewhere in the instance
>>the slot-names authored, then did what you did with the initargs/values.
>>
>>hth,kzo
> 
> 
> The important part of it isn't really the ability to copy the CLOS
> objects, it is the ability to mutate them.

Mutating is a special case of copying, don't you think?

kt
From: Kenny
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <493612e5$0$14285$607ed4bc@cv.net>
Kenny wrote:
> ··················@gmail.com wrote:
> 
>> On Dec 2, 9:16 pm, Kenny <·········@gmail.com> wrote:
>>
>>>> |> | Unfortunately, the fact that you are inventing possible use cases
>>>> |> | proves my point: you have no use case arising from your working 
>>>> code,
>>>> |> | you were just tool-fantasizing. Now where did I leave that beach
>>>> |> | rant...?
>>>> |>
>>>> |> Painting the toolshed beats dealing with the harder problems that 
>>>> the
>>>> |> app at hand youre writing presents!  Surely you knew that!  |
>>>> | I believe anyone who has tested a paint color on a different surface
>>>> | under different lighting conditions than the thing one actually
>>>> | intends to paint would like a word with you about the value of this
>>>> | argument by analogy.
>>>
>>>
>>>> I couldn't come up with a better non-sequitur!
>>>
>>>
>>> I feel a House coming on, or maybe some bloggery. In brief, there are
>>> times when distillation to a minimal case rocks, usually when faced with
>>> a bug cuz as long as the bug still happens one has not changed the
>>> subject. Otherwise, you generally end up with people working on an
>>> unrelated problem, which is why argument by analogy is so useless.
>>>
>>> Meanwhile, Pascal reminded me of the wild CLOS copying code I did write
>>> once. What was the requirement? I had to copy CLOS instances. Literally,
>>> that was all I had to do. MWUAGAHAHAHAHAHAHAHAHAHAHAHAHAHAHA.
>>>
>>> It was a DB partial-replication scheme where AllegoStore (persistent
>>> CLOS) was the DB. And it turned out beautifully that we did want to copy
>>> only those slots that had been authored at make-instance time and let
>>> other slots pick up their values (if unauthored at m/i time) from the
>>> class defintion.
>>>
>>> Because classes change and in our case we very much wanted those changed
>>> reflected in new instances. How scary is that? Persistent cells were
>>> involved, too. Woohoo!
>>>
>>> IIRC, I hit the problem over the head, storing somewhere in the instance
>>> the slot-names authored, then did what you did with the initargs/values.
>>>
>>> hth,kzo
>>
>>
>>
>> The important part of it isn't really the ability to copy the CLOS
>> objects, it is the ability to mutate them.
> 
> 
> Mutating is a special case of copying, don't you think?

Well, no, mutating is the opposite of copying, but we know what you mean.

kt
From: ··················@gmail.com
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <02583713-9f7c-4ad2-adf5-22f6a98874ff@h20g2000yqn.googlegroups.com>
On Dec 3, 12:02 am, Kenny <·········@gmail.com> wrote:
> Kenny wrote:
> > ··················@gmail.com wrote:
>
> >> On Dec 2, 9:16 pm, Kenny <·········@gmail.com> wrote:
>
> >>>> |> | Unfortunately, the fact that you are inventing possible use cases
> >>>> |> | proves my point: you have no use case arising from your working
> >>>> code,
> >>>> |> | you were just tool-fantasizing. Now where did I leave that beach
> >>>> |> | rant...?
> >>>> |>
> >>>> |> Painting the toolshed beats dealing with the harder problems that
> >>>> the
> >>>> |> app at hand youre writing presents!  Surely you knew that!  |
> >>>> | I believe anyone who has tested a paint color on a different surface
> >>>> | under different lighting conditions than the thing one actually
> >>>> | intends to paint would like a word with you about the value of this
> >>>> | argument by analogy.
>
> >>>> I couldn't come up with a better non-sequitur!
>
> >>> I feel a House coming on, or maybe some bloggery. In brief, there are
> >>> times when distillation to a minimal case rocks, usually when faced with
> >>> a bug cuz as long as the bug still happens one has not changed the
> >>> subject. Otherwise, you generally end up with people working on an
> >>> unrelated problem, which is why argument by analogy is so useless.
>
> >>> Meanwhile, Pascal reminded me of the wild CLOS copying code I did write
> >>> once. What was the requirement? I had to copy CLOS instances. Literally,
> >>> that was all I had to do. MWUAGAHAHAHAHAHAHAHAHAHAHAHAHAHAHA.
>
> >>> It was a DB partial-replication scheme where AllegoStore (persistent
> >>> CLOS) was the DB. And it turned out beautifully that we did want to copy
> >>> only those slots that had been authored at make-instance time and let
> >>> other slots pick up their values (if unauthored at m/i time) from the
> >>> class defintion.
>
> >>> Because classes change and in our case we very much wanted those changed
> >>> reflected in new instances. How scary is that? Persistent cells were
> >>> involved, too. Woohoo!
>
> >>> IIRC, I hit the problem over the head, storing somewhere in the instance
> >>> the slot-names authored, then did what you did with the initargs/values.
>
> >>> hth,kzo
>
> >> The important part of it isn't really the ability to copy the CLOS
> >> objects, it is the ability to mutate them.
>
> > Mutating is a special case of copying, don't you think?
>
> Well, no, mutating is the opposite of copying, but we know what you mean.
>
> kt

I'm not a computer scientist so I think of it primarily in the genetic
sense,
where mutations are caused through imperfect copying, so I'd probably
go with the term 'subset'.

(Luckily (or not?) English is a do what I mean language)

But you are quite right that arbitrary copying of objects isn't
terribly useful,
if only because you can just point to the original one.
From: Kaz Kylheku
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <20081218185514.311@gmail.com>
On 2008-12-03, ··················@gmail.com <··················@gmail.com>
wrote:
> On Dec 3, 12:02 am, Kenny <·········@gmail.com> wrote:
>> Well, no, mutating is the opposite of copying, but we know what you mean.
>>
>> kt
>
> But you are quite right that arbitrary copying of objects isn't
> terribly useful,
> if only because you can just point to the original one.

You mean that one on the server in Yukon behind a 56 kbps line?

/You/ go point to that one; I will make do with the one here.

:)
From: Pascal Costanza
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <6pic1bF89apdU1@mid.individual.net>
Madhu wrote:
> (:I put `misguided' in the subject to catch Kenny's attention:)

Kenny won't help. He will only tell you that CLOS sucks and that you 
should use cells. Or something.

> The situation is not new.  One wishes to create a new object which is
> slightly different from another object, i.e. where a few slots have
> different values.  I found the sweetest syntax to do this was in CMU's
> KR (when using Create-Instance during prototype creation).  In CLOS, I'd
> like to use the MAKE-INSTANCE mechanism to do the defaulting like this:
> 
> 	(MAKE-INSTANCE 'Class1 :defaults obj2 :slot1 val1 :slot2 val2)
> 
> should fill in SLOT1 and SLOT2 from this form and use all other initargs
> from obj2 when creating an instance of Class1.  Here is an
> implementation which uses an around method on iNITIALIZE-INSTANCE to
> accomplish this.  For this to work CLASS1 would just need to subclass
> the magic mixin class DEFAULT-COPYING-MIXIN.  This works for me in PCL
> and under LW.  How correct is it?

I think this looks decent. I see only two potential problems:

- Somebody may want to inherit from a class that already uses :default 
as an initialization keyword. You may want to consider using non-keyword 
symbol from your own package instead.

- CLOS allows the same initialization keyword to be used for several 
different slots. So your pick of an arbitrary initialization keyword 
from the slot definition metaobject may not be robust. Therefore, it may 
be better to implement your extension in a method on shared-initialize, 
where you get explicit information about which slots were initialized by 
an initarg, and which are about to be initialized by an initform. But 
most CLOS classes probably don't have this problem, so your solution may 
be good enough. If you want to make this part of a publicly available 
library, I would be more careful, though.


Pascal

> --
> Madhu
> 
> 
> #+nil
> (mapcar (lambda (x &aux (a (find-symbol x #+pcl :pcl #-pcl :clos)))
>           (and a (import a)))
>         '("CLASS-SLOTS" "SLOT-DEFINITION-INITARGS" "CLASS-DIRECT-SLOTS"
>           "SLOT-DEFINITION-NAME"))
> 
> 
> (defclass default-copying-mixin ()
>   ()
>   (:documentation "Magic class.  MAKE-INSTANCE on subclasses can supply
> a :DEFAULT OBJ keyword argument to default slot values from that OBJ."))
> 
> 
> (defmethod initialize-instance :around ((obj default-copying-mixin) &rest args
>                                         &key default &allow-other-keys
>                                         &aux initarg)
>   (when default
>     (setq args
>           (nconc
>            ;; snarf initargs from DEFAULT object
>            (loop for slot in (class-direct-slots (class-of default))
>                  for slot-name = (slot-definition-name slot)
>                  when (and (slot-exists-p default slot-name)
>                            (slot-boundp default slot-name)
>                            (setq initarg (car (slot-definition-initargs slot))))
>                  nconc (list initarg (slot-value default slot-name)))
>            ;; frob args to remove the DEFAULT keyword arg
>            (loop for prev = nil then cons for cons on args
>                  when (eql (car cons) :default)
>                  if (endp prev) return (cddr args)
>                  else return (prog1 args (setf (cdr prev) (cddr cons)))))))
>   (apply #'call-next-method obj args))


-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Michael Weber
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <4e9c836d-5f5c-4dba-b6c4-aad79a5a21b5@h5g2000yqh.googlegroups.com>
On Dec 1, 3:52 pm, Pascal Costanza <····@p-cos.net> wrote:
> I think this looks decent. I see only two potential problems:
>
> - Somebody may want to inherit from a class that already uses :default
> as an initialization keyword. You may want to consider using non-keyword
> symbol from your own package instead.
>
> - CLOS allows the same initialization keyword to be used for several
> different slots. So your pick of an arbitrary initialization keyword
> from the slot definition metaobject may not be robust.
[...]
> If you want to make this part of a publicly available
> library, I would be more careful, though.

We could compare to the (more or less) standard take on copying CLOS
objects.  Here's an implementation I wrote some time ago, I have no
doubt there are similar ones floating around):
<http://www.foldr.org/~michaelw/lisp/copy-instance.lisp>

Usage: (copy-instance obj :slot1 'foo :slot2 'bar ...)  where :slot1
and :slot2 are initargs for obj's class.
From: Pascal Costanza
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <6pn0ncF8q0jcU1@mid.individual.net>
Michael Weber wrote:
> On Dec 1, 3:52 pm, Pascal Costanza <····@p-cos.net> wrote:
>> I think this looks decent. I see only two potential problems:
>>
>> - Somebody may want to inherit from a class that already uses :default
>> as an initialization keyword. You may want to consider using non-keyword
>> symbol from your own package instead.
>>
>> - CLOS allows the same initialization keyword to be used for several
>> different slots. So your pick of an arbitrary initialization keyword
>> from the slot definition metaobject may not be robust.
> [...]
>> If you want to make this part of a publicly available
>> library, I would be more careful, though.
> 
> We could compare to the (more or less) standard take on copying CLOS
> objects.  Here's an implementation I wrote some time ago, I have no
> doubt there are similar ones floating around):
> <http://www.foldr.org/~michaelw/lisp/copy-instance.lisp>
> 
> Usage: (copy-instance obj :slot1 'foo :slot2 'bar ...)  where :slot1
> and :slot2 are initargs for obj's class.

Yes, much better. No need to force this functionality into 
make-instance. It's clear that you want one or the other anyway.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Madhu
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <m3fxl5k0vf.fsf@moon.robolove.meer.net>
* Pascal Costanza <··············@mid.individual.net> :
Wrote on Wed, 03 Dec 2008 10:10:04 +0100:

|> Usage: (copy-instance obj :slot1 'foo :slot2 'bar ...)  where :slot1
|> and :slot2 are initargs for obj's class.
|
| Yes, much better. No need to force this functionality into
| make-instance. It's clear that you want one or the other anyway.

No, the reason I ended up with make-instance was that I specifically
wanted to create an instance of an object in a different (but related)
class from the object whose slots I wanted to copy.

--
Madhu
From: Pascal Costanza
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <6pnf5hF8p77aU1@mid.individual.net>
Madhu wrote:
> * Pascal Costanza <··············@mid.individual.net> :
> Wrote on Wed, 03 Dec 2008 10:10:04 +0100:
> 
> |> Usage: (copy-instance obj :slot1 'foo :slot2 'bar ...)  where :slot1
> |> and :slot2 are initargs for obj's class.
> |
> | Yes, much better. No need to force this functionality into
> | make-instance. It's clear that you want one or the other anyway.
> 
> No, the reason I ended up with make-instance was that I specifically
> wanted to create an instance of an object in a different (but related)
> class from the object whose slots I wanted to copy.

(change-class
   (copy-instance some-instance)
   'some-class
   :slot1 value1
   :slot2 value2
   ...)


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Kenny
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <49369565$0$4900$607ed4bc@cv.net>
Pascal Costanza wrote:
> Madhu wrote:
> 
>> * Pascal Costanza <··············@mid.individual.net> :
>> Wrote on Wed, 03 Dec 2008 10:10:04 +0100:
>>
>> |> Usage: (copy-instance obj :slot1 'foo :slot2 'bar ...)  where :slot1
>> |> and :slot2 are initargs for obj's class.
>> |
>> | Yes, much better. No need to force this functionality into
>> | make-instance. It's clear that you want one or the other anyway.
>>
>> No, the reason I ended up with make-instance was that I specifically
>> wanted to create an instance of an object in a different (but related)
>> class from the object whose slots I wanted to copy.
> 
> 
> (change-class
>   (copy-instance some-instance)
>   'some-class
>   :slot1 value1
>   :slot2 value2
>   ...)
> 

No machine that goes ping? /Now/ cue the anti-CLOS rant!

:)

kt
From: Pascal Costanza
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <6pnju1F93iu1U1@mid.individual.net>
Kenny wrote:
> Pascal Costanza wrote:
>> Madhu wrote:
>>
>>> * Pascal Costanza <··············@mid.individual.net> :
>>> Wrote on Wed, 03 Dec 2008 10:10:04 +0100:
>>>
>>> |> Usage: (copy-instance obj :slot1 'foo :slot2 'bar ...)  where :slot1
>>> |> and :slot2 are initargs for obj's class.
>>> |
>>> | Yes, much better. No need to force this functionality into
>>> | make-instance. It's clear that you want one or the other anyway.
>>>
>>> No, the reason I ended up with make-instance was that I specifically
>>> wanted to create an instance of an object in a different (but related)
>>> class from the object whose slots I wanted to copy.
>>
>>
>> (change-class
>>   (copy-instance some-instance)
>>   'some-class
>>   :slot1 value1
>>   :slot2 value2
>>   ...)
>>
> 
> No machine that goes ping? /Now/ cue the anti-CLOS rant!

It took some more time this time, but you proved my point.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Madhu
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <m38wqwkala.fsf@moon.robolove.meer.net>
* Pascal Costanza <··············@mid.individual.net> :
Wrote on Wed, 03 Dec 2008 15:37:53 +0100:

|>>> |> Usage: (copy-instance obj :slot1 'foo :slot2 'bar ...)  where :slot1
|>>> |> and :slot2 are initargs for obj's class.
|>>> |
|>>> | Yes, much better. No need to force this functionality into
|>>> | make-instance. It's clear that you want one or the other anyway.
|>>>
|>>> No, the reason I ended up with make-instance was that I specifically
|>>> wanted to create an instance of an object in a different (but related)
|>>> class from the object whose slots I wanted to copy.
|
|>> (change-class
|>>   (copy-instance some-instance)
|>>   'some-class
|>>   :slot1 value1
|>>   :slot2 value2
|>>   ...)

Of course.

But if you go back to my initial post, what I was saying there was

    (MAKE-INSTANCE 'OBJECT :DEFAULTS ...) 

represents more accurately the intention in my code.  The intention,
I've repeated again, quoted above.  This also matches more closely the
CREATE-INSTANCE syntax that I cited.

[Sorry to be boneheaded, but I'm afraid you were missing my point]

--
Madhu
From: Pascal Costanza
Subject: Re: New CLOS techniques: Copying objects
Date: 
Message-ID: <6ppk44F9a7g9U1@mid.individual.net>
Madhu wrote:
> * Pascal Costanza <··············@mid.individual.net> :
> Wrote on Wed, 03 Dec 2008 15:37:53 +0100:
> 
> |>>> |> Usage: (copy-instance obj :slot1 'foo :slot2 'bar ...)  where :slot1
> |>>> |> and :slot2 are initargs for obj's class.
> |>>> |
> |>>> | Yes, much better. No need to force this functionality into
> |>>> | make-instance. It's clear that you want one or the other anyway.
> |>>>
> |>>> No, the reason I ended up with make-instance was that I specifically
> |>>> wanted to create an instance of an object in a different (but related)
> |>>> class from the object whose slots I wanted to copy.
> |
> |>> (change-class
> |>>   (copy-instance some-instance)
> |>>   'some-class
> |>>   :slot1 value1
> |>>   :slot2 value2
> |>>   ...)
> 
> Of course.
> 
> But if you go back to my initial post, what I was saying there was
> 
>     (MAKE-INSTANCE 'OBJECT :DEFAULTS ...) 
> 
> represents more accurately the intention in my code.  The intention,
> I've repeated again, quoted above.  This also matches more closely the
> CREATE-INSTANCE syntax that I cited.
> 
> [Sorry to be boneheaded, but I'm afraid you were missing my point]

(defun create-instance (class default &rest initargs)
   (apply #'change-class
     (copy-instance default)
     class
     initargs))


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Kenny
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <4934324e$0$20301$607ed4bc@cv.net>
Pascal Costanza wrote:
> Madhu wrote:
> 
>> (:I put `misguided' in the subject to catch Kenny's attention:)
> 
> 
> Kenny won't help. He will only tell you that CLOS sucks and that you 
> should use cells. Or something.

You forgot the obvious: I will pick on you for not asking the poor noob 
why they want such a thing.

In a prototyping OO model, such copying is precisely how one handles the 
class-instance deal of other systems, so what we have here (it seems) is 
an unfortunate conflation of two models into one.

Should be fun!

p,k
From: Pascal Costanza
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <6pjaukF8dakbU1@mid.individual.net>
Kenny wrote:
> Pascal Costanza wrote:
>> Madhu wrote:
>>
>>> (:I put `misguided' in the subject to catch Kenny's attention:)
>>
>>
>> Kenny won't help. He will only tell you that CLOS sucks and that you 
>> should use cells. Or something.
> 
> You forgot the obvious: I will pick on you for not asking the poor noob 
> why they want such a thing.
> 
> In a prototyping OO model, such copying is precisely how one handles the 
> class-instance deal of other systems, so what we have here (it seems) is 
> an unfortunate conflation of two models into one.

Sounds too academic to me.

I needed this before, I implemented something similar, and it was damn 
useful.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Madhu
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <m3k5akdrxl.fsf@moon.robolove.meer.net>
* Madhu <··············@moon.robolove.meer.net> :
Wrote on Mon, 01 Dec 2008 15:41:52 +0530:

| 	(MAKE-INSTANCE 'Class1 :defaults obj2 :slot1 val1 :slot2 val2)
|
| should fill in SLOT1 and SLOT2 from this form and use all other initargs
| from obj2 when creating an instance of Class1.  Here is an
| implementation which uses an around method on iNITIALIZE-INSTANCE to
| accomplish this.  For this to work CLASS1 would just need to subclass
| the magic mixin class DEFAULT-COPYING-MIXIN.  This works for me in PCL
| and under LW.  How correct is it?

[snip]

Oops! This code I posted would not work because I forgot to eliminate
redunant initargs. Correction inline:

| (defclass default-copying-mixin ()
|   ()
|   (:documentation "Magic class.  MAKE-INSTANCE on subclasses can supply
| a :DEFAULT OBJ keyword argument to default slot values from that OBJ."))
|
|
| (defmethod initialize-instance :around ((obj default-copying-mixin) &rest args
|                                         &key default &allow-other-keys
|                                         &aux initarg)
|   (when default
|     (setq args
|           (nconc
|            ;; snarf initargs from DEFAULT object
|            (loop for slot in (class-direct-slots (class-of default))
		       ;; or use class-slots here?
|                  for slot-name = (slot-definition-name slot)
|                  when (and (slot-exists-p default slot-name)
|                            (slot-boundp default slot-name)
|                            (setq initarg (car (slot-definition-initargs slot)))
;;     -------------------> add this conditional
			     (eql (getf args initarg args) args))
|                  nconc (list initarg (slot-value default slot-name)))
|            ;; frob args to remove the DEFAULT keyword arg
|            (loop for prev = nil then cons for cons on args
|                  when (eql (car cons) :default)
|                  if (endp prev) return (cddr args)
|                  else return (prog1 args (setf (cdr prev) (cddr cons)))))))
|   (apply #'call-next-method obj args))

--
Madhu
From: Pascal Costanza
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <6pic41F89apdU2@mid.individual.net>
Madhu wrote:
> * Madhu <··············@moon.robolove.meer.net> :
> Wrote on Mon, 01 Dec 2008 15:41:52 +0530:
> 
> | 	(MAKE-INSTANCE 'Class1 :defaults obj2 :slot1 val1 :slot2 val2)
> |
> | should fill in SLOT1 and SLOT2 from this form and use all other initargs
> | from obj2 when creating an instance of Class1.  Here is an
> | implementation which uses an around method on iNITIALIZE-INSTANCE to
> | accomplish this.  For this to work CLASS1 would just need to subclass
> | the magic mixin class DEFAULT-COPYING-MIXIN.  This works for me in PCL
> | and under LW.  How correct is it?
> 
> [snip]
> 
> Oops! This code I posted would not work because I forgot to eliminate
> redunant initargs. Correction inline:
> 
> | (defclass default-copying-mixin ()
> |   ()
> |   (:documentation "Magic class.  MAKE-INSTANCE on subclasses can supply
> | a :DEFAULT OBJ keyword argument to default slot values from that OBJ."))
> |
> |
> | (defmethod initialize-instance :around ((obj default-copying-mixin) &rest args
> |                                         &key default &allow-other-keys
> |                                         &aux initarg)
> |   (when default
> |     (setq args
> |           (nconc
> |            ;; snarf initargs from DEFAULT object
> |            (loop for slot in (class-direct-slots (class-of default))
> 		       ;; or use class-slots here?
> |                  for slot-name = (slot-definition-name slot)
> |                  when (and (slot-exists-p default slot-name)
> |                            (slot-boundp default slot-name)
> |                            (setq initarg (car (slot-definition-initargs slot)))
> ;;     -------------------> add this conditional
> 			     (eql (getf args initarg args) args))
> |                  nconc (list initarg (slot-value default slot-name)))
> |            ;; frob args to remove the DEFAULT keyword arg
> |            (loop for prev = nil then cons for cons on args
> |                  when (eql (car cons) :default)
> |                  if (endp prev) return (cddr args)
> |                  else return (prog1 args (setf (cdr prev) (cddr cons)))))))
> |   (apply #'call-next-method obj args))

You don't really need this extra test. Just switch the two loop forms, 
then the explicitly passed initargs will be in front and will thus take 
precedence. BTW, why do you test for slot-exists-p?

It may be important to filter out slots with :allocation :class...


Pascal


-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Madhu
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <m3bpvve0b8.fsf@moon.robolove.meer.net>
* Pascal Costanza <··············@mid.individual.net> :
Wrote on Mon, 01 Dec 2008 15:53:53 +0100:
| Madhu wrote:
|> Oops! This code I posted would not work because I forgot to eliminate
|> redunant initargs. Correction inline:

[snip]

| You don't really need this extra test. Just switch the two loop forms,
| then the explicitly passed initargs will be in front and will thus
| take precedence.

Yes, and I could just use REMF instead of frobbing the ARGS list, or
better still leave the :defaults keyword arguments alone: without
removing them (assuming nobody in the method combination's callstack is
interested in them, they will be ignored anyway)

However I decided if there are multiple :default arguments, I want to
handle all of them.  FTR I'm appending this (non destuctive) code to the
bottom of this post.

| BTW, why do you test for slot-exists-p?

I thought I had an issue when using CLASS-SLOTS from where I

| It may be important to filter out slots with :allocation :class...

I thought about that --- the problem I considered was the danger was
that some global slot value might get inadvertantly changed (or is there
another issue). In this case I assumed it would be the same value
getting overwritten.  `:allocation :class' semantics are tricky enough
when used in a non-trivial way, ... 

--
thx, Madhu

PS: Cleaned up (or more messy version depending on your POV :)

(defclass default-copying-mixin ()
  ()
  (:documentation "Magic class.  MAKE-INSTANCE on subclasses can supply
a :DEFAULT OBJ keyword argument to default slot values from that OBJ."))


(defmethod initialize-instance :around ((obj default-copying-mixin) &rest args
					&key &allow-other-keys &aux initarg)
  (apply #'call-next-method obj
	 (append
	  args
	  (loop for (indicator default) on args by #'cddr
		when (eql indicator :default) nconc
		(loop for slot in (class-slots (class-of default))
		      for slot-name = (slot-definition-name slot)
		      when (and (slot-boundp default slot-name)
				(setq initarg
				      (car (slot-definition-initargs slot))))
		      nconc (list initarg (slot-value default slot-name)))))))
From: Kaz Kylheku
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <20081217094512.456@gmail.com>
On 2008-12-01, Madhu <·······@meer.net> wrote:
> KR (when using Create-Instance during prototype creation).  In CLOS, I'd
> like to use the MAKE-INSTANCE mechanism to do the defaulting like this:
>
> 	(MAKE-INSTANCE 'Class1 :defaults obj2 :slot1 val1 :slot2 val2)
>
> should fill in SLOT1 and SLOT2 from this form and use all other initargs
> from obj2 when creating an instance of Class1. 

Gee, this sounds a lot like:

   (make-pathname ... :defaults some-other-pathname)

:)
From: Björn Lindberg
Subject: Re: [misguided?] New CLOS techniques: Copying objects
Date: 
Message-ID: <9mpiqq32bzz.fsf@muvclx01.cadence.com>
Kaz Kylheku <········@gmail.com> writes:

> On 2008-12-01, Madhu <·······@meer.net> wrote:

Problem:

>> KR (when using Create-Instance during prototype creation).  In CLOS, I'd
>> like to use the MAKE-INSTANCE mechanism to do the defaulting like this:
>>
>> 	(MAKE-INSTANCE 'Class1 :defaults obj2 :slot1 val1 :slot2 val2)
>>
>> should fill in SLOT1 and SLOT2 from this form and use all other initargs
>> from obj2 when creating an instance of Class1. 

Observation:

> Gee, this sounds a lot like:
>
>    (make-pathname ... :defaults some-other-pathname)

Solution: Stuff your data not in CLOS instances, but in pathnames and
you will get the defaulting for free!

Anyone who thinks this would be abusing the pathname system, may
ponder that difference between class and prototype based object
systems one more time...


Bj�rn Lindberg