From: Martin Raspaud
Subject: About change-class
Date: 
Message-ID: <m3d64pvkpn.fsf@lns-th2-14-82-64-61-173.adsl.proxad.net>
Hi all,

Is there a way of performing a "change-class" on 2 objects
simultaneously ?

For example, I define the following classes : foo, bar and foobar.

CL-USER> (defclass foo () ((foo-slot :initarg :foo-slot)))
#<STANDARD-CLASS FOO {4868038D}>
CL-USER> (defclass bar () ((bar-slot :initarg :bar-slot)))
#<STANDARD-CLASS BAR {4868F195}>
CL-USER> (defclass foobar (foo bar) ())
#<STANDARD-CLASS FOOBAR {487199DD}>

Then I make an instance of each of them :

CL-USER> (setf myfoo (make-instance 'foo :foo-slot 1))
#<FOO {48721FC5}>
CL-USER> (setf mybar (make-instance 'bar :bar-slot 2))
#<BAR {48726265}>


An now I would like something like :

CL-USER> (change-class myfoo mybar 'foobar)

so I get an instance containing the slots of either myfoo and mybar...

What do you think ?

Martin

From: Barry Margolin
Subject: Re: About change-class
Date: 
Message-ID: <barmar-C86FFB.17595927052004@comcast.dca.giganews.com>
In article <··············@lns-th2-14-82-64-61-173.adsl.proxad.net>,
 Martin Raspaud <······@lns-th2-14-82-64-61-173.adsl.proxad.net> wrote:

> Hi all,
> 
> Is there a way of performing a "change-class" on 2 objects
> simultaneously ?
> 
> For example, I define the following classes : foo, bar and foobar.
> 
> CL-USER> (defclass foo () ((foo-slot :initarg :foo-slot)))
> #<STANDARD-CLASS FOO {4868038D}>
> CL-USER> (defclass bar () ((bar-slot :initarg :bar-slot)))
> #<STANDARD-CLASS BAR {4868F195}>
> CL-USER> (defclass foobar (foo bar) ())
> #<STANDARD-CLASS FOOBAR {487199DD}>
> 
> Then I make an instance of each of them :
> 
> CL-USER> (setf myfoo (make-instance 'foo :foo-slot 1))
> #<FOO {48721FC5}>
> CL-USER> (setf mybar (make-instance 'bar :bar-slot 2))
> #<BAR {48726265}>
> 
> 
> An now I would like something like :
> 
> CL-USER> (change-class myfoo mybar 'foobar)
> 
> so I get an instance containing the slots of either myfoo and mybar...
> 
> What do you think ?

I recommend writing a new method to do this:

(defmethod make-foobar ((f foo) (b bar))
  (make-instance 'foobar :foo-slot (slot-value f 'foo-slot)
                         :bar-slot (slot-value b 'bar-slot)))

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Kalle Olavi Niemitalo
Subject: Re: About change-class
Date: 
Message-ID: <87isehn012.fsf@Astalo.kon.iki.fi>
Martin Raspaud <······@lns-th2-14-82-64-61-173.adsl.proxad.net> writes:

> CL-USER> (change-class myfoo mybar 'foobar)
>
> so I get an instance containing the slots of either myfoo and mybar...
>
> What do you think ?

I don't think that should be directly possible.  One property of
CHANGE-CLASS is that (eq foo (change-class foo 'bar)) is T.  If
CHANGE-CLASS could take two instances like you suggest, I'd
expect (eq myfoo mybar) to be T afterwards, even though it has
been NIL before.  Currently, there is no operator to merge object
identities like that.

You can give initialization arguments to CHANGE-CLASS, though:

  (change-class myfoo 'foobar
                :bar-slot (slot-value mybar 'bar-slot))

If I remember correctly, extracting suitable initargs from an
instance of an arbitrary class requires use of the MOP.  One
could try parsing the output of MAKE-LOAD-FORM-SAVING-SLOTS
instead, but I suppose that would be even less portable.