From: ctu
Subject: [how] adding new slots interactively
Date: 
Message-ID: <1138122075.356817.114290@f14g2000cwb.googlegroups.com>
Wondering how i can add a new slot to an existing class ?

- i just want to add a new slot, not redefining the entire class. It is
for use in interactive dev.
  i don't want to re-evaluate the entire class definition.

- i look cl & clos api and didn't find the solution. no 'add-slot' ...

- i found a bad way to do that : using ensure-class and merging with
the old-definition.

From: sross
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138133167.700661.148070@g44g2000cwa.googlegroups.com>
ctu wrote:
> Wondering how i can add a new slot to an existing class ?
>
> - i just want to add a new slot, not redefining the entire class. It is
> for use in interactive dev.
>   i don't want to re-evaluate the entire class definition.
>
> - i look cl & clos api and didn't find the solution. no 'add-slot' ...
>
> - i found a bad way to do that : using ensure-class and merging with
> the old-definition.

>From what I've found the only way to do this is to use ensure class and

merge the direct-slots with the slots that you want added.
This is what I've been using.

(defun direct-slot-defn->initarg (slot-defn)
  (list :name (slot-definition-name slot-defn)
        :readers (slot-definition-readers slot-defn)
        :writers (slot-definition-writers slot-defn)
        :initform (slot-definition-initform slot-defn)
        :initargs (slot-definition-initargs slot-defn)
        :initfunction (slot-definition-initfunction slot-defn)))

(defun add-slot-to-class (class name &key (initform nil)
                                accessors readers writers
                                initargs
                                (initfunction (constantly nil)))
  (check-type class symbol)
  (let ((new-slots (list (list :name name
                               :readers (union accessors readers)
                               :writers (union writers
                                               (mapcar #'(lambda (x)
                                                           (list 'setf
x))
                                                       accessors)
                                               :test #'equal)
                               :initform initform
                               :initargs initargs
                               :initfunction initfunction))))
    (dolist (slot-defn (class-direct-slots (find-class class)))
      (push (direct-slot-defn->initarg slot-defn)
            new-slots))
    (ensure-class class :direct-slots new-slots)))

Apologies for any indentation funnies.

Cheers, 
  Sean
From: sross
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138133585.599578.86480@g49g2000cwa.googlegroups.com>
Ahem,
  Sorry, this requires certain packages to be imported
  ie. for
  sbcl  ; :sb-mop
  lispworks ; :clos
  cmucl ; :pcl

otherwise various symbols will be undefined.
(I think these packages are correct, it's only been tested on
Lispworks)

Cheers,
  Sean.
From: Pascal Bourguignon
Subject: Re: [how] adding new slots interactively
Date: 
Message-ID: <87d5ih4k2t.fsf@thalassa.informatimago.com>
"ctu" <······@yahoo.com> writes:

> Wondering how i can add a new slot to an existing class ?

Doing nothing special:

[14]> (defclass exemple () (a))
#<STANDARD-CLASS EXEMPLE>
[15]> (defparameter o (make-instance 'exemple))
O
[16]> (inspect o)
#<COMMON-LISP-USER::EXEMPLE #x204C8B56>:  standard object
 type: COMMON-LISP-USER::EXEMPLE
0 [A]:  |#<unbound>|
INSPECT-- type :h for help; :q to return to the REPL ---> :q

[17]> (defclass exemple () (a b))
WARNING: DEFCLASS: Class EXEMPLE (or one of its ancestors) is being redefined,
         instances are obsolete
#<STANDARD-CLASS EXEMPLE :VERSION 1>
[18]> (inspect o)
#<COMMON-LISP-USER::EXEMPLE #x204C8B56>:  standard object
 type: COMMON-LISP-USER::EXEMPLE
0 [A]:  |#<unbound>|
1 [B]:  |#<unbound>|
INSPECT-- type :h for help; :q to return to the REPL ---> :q

[19]> 



> - i just want to add a new slot, not redefining the entire class. It is
> for use in interactive dev.
>   i don't want to re-evaluate the entire class definition.
>
> - i look cl & clos api and didn't find the solution. no 'add-slot' ...
>
> - i found a bad way to do that : using ensure-class and merging with
> the old-definition.

This is not a bad way, this is THE way.  DEFCLASS is implemented with
ENSURE-CLASS.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
You're always typing.
Well, let's see you ignore my
sitting on your hands.
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138124032.996216.259890@z14g2000cwz.googlegroups.com>
Perhaps, i have mis-written what i want : i didn't want to redefine the
entire class.

For me (defclass exemple () (a b)) is just that. I just want to add the
new slot "b". I don't have to know at that point that there is an
existing direct slot called "a" to do the job.

I really just want to add the slot "b". with a simple call like
(add-slot (find-class 'exemple) '(b :reader b)) or something like that.
From: Pascal Bourguignon
Subject: Re: adding new slots interactively
Date: 
Message-ID: <878xt54fyb.fsf@thalassa.informatimago.com>
"ctu" <······@yahoo.com> writes:

> Perhaps, i have mis-written what i want : i didn't want to redefine the
> entire class.
>
> For me (defclass exemple () (a b)) is just that. I just want to add the
> new slot "b". I don't have to know at that point that there is an
> existing direct slot called "a" to do the job.

Read again the dribble!  The only effect is to add a slot.


You could write something like this:

(shadow 'defclass)
(defmacro defclass (name superclasses slots &rest options)
  `(prog1
     (cl:defclass ,name ,superclasses ,slots ,@options)
     (setf (get ',name 'defclass) 
            '(cl:defclass ,name ,superclasses ,slots ,@options))))

(defun add-slot (class slot)
  (setf (fourth (get class 'defclass))
        (append (fourth (get class 'defclass)) (list slot)))
  (eval (get class 'defclass)))


[392]> (defclass example () (a))
#<STANDARD-CLASS EXAMPLE>
[393]> (setf o (make-instance 'example))
#<EXAMPLE #x2067D28E>
[394]> (inspect o)
#<COMMON-LISP-USER::EXAMPLE #x2067D28E>:  standard object
 type: COMMON-LISP-USER::EXAMPLE
0 [A]:  |#<unbound>|
INSPECT-- type :h for help; :q to return to the REPL ---> :q

[395]> (add-slot 'example '(b :initform 2))
WARNING: CLOS:DEFCLASS: Class EXAMPLE (or one of its ancestors) is being
         redefined, instances are obsolete
#<STANDARD-CLASS EXAMPLE :VERSION 1>
[396]> (inspect o)
#<COMMON-LISP-USER::EXAMPLE #x2067D28E>:  standard object
 type: COMMON-LISP-USER::EXAMPLE
0 [A]:  |#<unbound>|
1 [B]:  2
INSPECT-- type :h for help; :q to return to the REPL ---> :q

[397]> 


> I really just want to add the slot "b". with a simple call like
> (add-slot (find-class 'exemple) '(b :reader b)) or something like that.

If you want to  be able to pass a class instead  of a class name, then
use a hash-table instead of the property list above.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

READ THIS BEFORE OPENING PACKAGE: According to certain suggested
versions of the Grand Unified Theory, the primary particles
constituting this product may decay to nothingness within the next
four hundred million years.
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138201042.798839.279580@g47g2000cwa.googlegroups.com>
This means that we can only add a slot to classes created by the new
defclass... It doesn't work on cl:defclass one.

btw, sross gave an implementation which corresponds to what i have
done. Using clos inspection to re-def the class.

I know that only the new slot will be added, but it shows that in clos,
we can't tell the interpreter to add a slot. We can only tell him to
implement the difference with a new definition (which may result in
just adding a slot). i'm not pleased with that...
From: Thomas F. Burdick
Subject: Re: adding new slots interactively
Date: 
Message-ID: <xcvmzhky9g5.fsf@conquest.OCF.Berkeley.EDU>
"ctu" <······@yahoo.com> writes:

> Perhaps, i have mis-written what i want : i didn't want to redefine the
> entire class.

Adding a new slot to the existing class *is* redefining it.  Nothing
bad happens when you redefine a class, so how about a question for
you: why do you think you should be avoiding redefining the class?

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138202139.301326.25600@g47g2000cwa.googlegroups.com>
To redefine a class you have to know all informations about it : clos
implementation.
To add a new slot you surely have to know some informations about it (
not necessarily all ) : clos implementation
To ASK to add a new slot, i hope users have not to to know all
informations about it : user(lisp program) <-> clos interaction.

Slot is a concept from the clos level. add-slot should belong to
clos-level. I'm firmly thinking it is a big miss from the clos api.
From: Kenny Tilton
Subject: Re: adding new slots interactively
Date: 
Message-ID: <ieOBf.4819$yE4.4691@news-wrt-01.rdc-nyc.rr.com>
ctu wrote:
> 
> Slot is a concept from the clos level. add-slot should belong to
> clos-level. I'm firmly thinking it is a big miss from the clos api.
> 

Ah, classic Ilias Syndrome. The guy is simultaneously asking how CLOS 
works and explaining what is wrong with it.

We get this once a month, right? Fascinating. Reminds me of people who 
buy superfast sports cars and then wrap them around trees before their 
driving skills catch up with their new toy.

kenny
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138210066.240730.202940@g47g2000cwa.googlegroups.com>
I'm not asking how CLOS works. I was asking if i have not missed
something from it. Because sometimes it happens that i miss something,
not you ?

I was asking if we can add a slot without redefining a class ( using
defclass or ensure-class). I asked this because ihmo it seems a big
mistake not including such an api. So i suspect a miss from me. So i
ask here. From the answers, it seems that there's no such api. So i
expressed my disappointment about this.

I gave reasons for what i have said. You may disagree. But it's not
very smart to just give some subjective opinions.
From: Kenny Tilton
Subject: Re: adding new slots interactively
Date: 
Message-ID: <vePBf.4824$yE4.498@news-wrt-01.rdc-nyc.rr.com>
ctu wrote:
> I'm not asking how CLOS works. I was asking if i have not missed
> something from it. Because sometimes it happens that i miss something,
> not you ?

Nonsense. You wrote: "I need to add a slot dynamically because it is 
WHAT i need." ie, Your random choice of implementation mechanism was now 
exactly and only what you needed, the only thing that would work, and we 
here on c.l.l were not allowed to question your choice of implementation 
mechanism. Instead, we were supposed along with you to curse CLOS:

"it shows that in clos, we can't tell the interpreter to add a slot. 
...i'm not pleased with that.."

Stop the Lisp world, you want to get off?

> 
> I was asking if we can add a slot without redefining a class ( using
> defclass or ensure-class). I asked this because ihmo it seems a big
> mistake not including such an api. So i suspect a miss from me. So i
> ask here. From the answers, it seems that there's no such api. So i
> expressed my disappointment about this.
> 
> I gave reasons for what i have said. You may disagree. But it's not
> very smart to just give some subjective opinions.
> 

Subjectivity on Usenet? God forbid.

kenny
From: Kenny Tilton
Subject: Re: adding new slots interactively
Date: 
Message-ID: <HDYBf.6494$cj3.288@news-wrt-01.rdc-nyc.rr.com>
Kenny Tilton wrote:
> ctu wrote:
> 
>> I'm not asking how CLOS works. I was asking if i have not missed
>> something from it.

Not from CLOS, but there /is/ cl-xml and I believe another XML parser 
library for CL.

What they would do (I am only guessing) is have classes for XML nodes 
etc qua XML syntax. ie, They use CLOS to emulate XML, not to realize in 
CLOS clases the schema you are representing in XML. You probably only 
WANT the former whether you know it or not, so not being able to add 
slots is no loss.

kenny
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138459602.660057.80190@g14g2000cwa.googlegroups.com>
>Not from CLOS, but there /is/ cl-xml and I believe another XML parser
>library for CL.

>What they would do (I am only guessing) is have classes for XML nodes
>etc qua XML syntax. ie, They use CLOS to emulate XML, not to realize in
>CLOS clases the schema you are representing in XML. You probably only
>WANT the former whether you know it or not, so not being able to add
>slots is no loss.

i'm actually using such a parser. This gives me a list representing an
xml document. This list is used to instantiate a class representing the
corresponding document-type. This has 2 advantages : to have accessors
implemented automatically and since my class are a lazy-class they only
create what is accessed, example :

xml document = <top a1="top level attribute"  <second_level a2="second
level attribute">>

parsed by cl-xml, it gives me a list :
(top :a1 "top level attribute" (second_level :a2 "second level
attribute"))
put it in a variable DOC.

i have also a document-type object representing the document type :
(def-doc-type (top :a1 (second-level :a2)))

Evaluating this expression above create a doc-type instance. The macro
just create a declarative representation of the document type.

(create-doc-type-accessors (the 'doc-type 'top)) create accessors in a
special package say 'acc'. Some prefer create these stuff directly from
the def-doc-type macro (open for an other discussion ;-).

just create the object from the list representation generated by cl-xml
:
(setf D (make-xml-doc (the 'doc-type 'top) :list-repr DOC))

Now i may use from 'acc' package my documents very easily.

(use-package :acc)

(a1 D) => "top level attribute"
(second-level D) => <xml-element (second-level :a2 "second level
attribute")>
(a2 (second-level D)) => "second level attribute"

the goal of this is currently to define test-cases which are very easy
to write and read since lots of implementation details are gone.

(assert (equalp (a2 (second-level D)) "second level attribute"))
...
From: Fred Gilham
Subject: Re: adding new slots interactively
Date: 
Message-ID: <u7wtgnnimw.fsf@snapdragon.csl.sri.com>
What you want is an a-list.  It will allow you to add and remove
"slots" at random and as long as your objects (the a-lists) aren't too
big, performance should be reasonable.

(This is a serious suggestion.)

-- 
Fred Gilham                                         ······@csl.sri.com
The people who think that the power of big business is enormous are
mistaken...since big business depends entirely on the patronage of
those who buy its products: the biggest enterprise loses its power and
its influence when it loses its customers.         -- Ludwig Von Mises
From: Pascal Bourguignon
Subject: Re: adding new slots interactively
Date: 
Message-ID: <87acdjx9l8.fsf@thalassa.informatimago.com>
Fred Gilham <······@snapdragon.csl.sri.com> writes:

> What you want is an a-list.  It will allow you to add and remove
> "slots" at random and as long as your objects (the a-lists) aren't too
> big, performance should be reasonable.
>
> (This is a serious suggestion.)

Indeed.  An a-list or a hash-table when the number of slots becomes
greater than (between 5 to 30 according to the implementation).  This
has the added advantage that adding or removing a slot can be done
object per object, and that it's lightweight compared to the job CLOS
has to do when you add a slot.

-- 
__Pascal_Bourguignon__               _  Software patents are endangering
()  ASCII ribbon against html email (o_ the computer industry all around
/\  1962:DO20I=1.100                //\ the world http://lpf.ai.mit.edu/
    2001:my($f)=`fortune`;          V_/   http://petition.eurolinux.org/
From: Pascal Bourguignon
Subject: Re: adding new slots interactively
Date: 
Message-ID: <87r76vxezg.fsf@thalassa.informatimago.com>
"ctu" <······@yahoo.com> writes:
> I was asking if we can add a slot without redefining a class ( using
> defclass or ensure-class). I asked this because ihmo it seems a big
> mistake not including such an api. So i suspect a miss from me. So i
> ask here. From the answers, it seems that there's no such api. So i
> expressed my disappointment about this.

Note that in any case, to add a slot, that is to modify a class,  you
need to have a class description somewhere.

You are wanting to have the class description down inside CLOS.
I've proposed a defclass macro that keeps it up over the CLOS API,
along with an add-slot function that does what you want.  
Can't you use it and just be happy with it?



I suspect the reason why there's no API to change each detail of a
class is because anybody can write new meta-classes with new details,
so if CLOS enumerated add-slot, add-superclass, add-option, etc, it
would always be incomplete. 


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
You never feed me.
Perhaps I'll sleep on your face.
That will sure show you.
From: Kenny Tilton
Subject: Re: adding new slots interactively
Date: 
Message-ID: <FkHBf.6436$cj3.2776@news-wrt-01.rdc-nyc.rr.com>
Thomas F. Burdick wrote:
> "ctu" <······@yahoo.com> writes:
> 
> 
>>Perhaps, i have mis-written what i want : i didn't want to redefine the
>>entire class.
> 
> 
> Adding a new slot to the existing class *is* redefining it.  Nothing
> bad happens when you redefine a class, so how about a question for
> you: why do you think you should be avoiding redefining the class?
> 

Then can we ask why he thinks he needs to add a slot dynamically?

btw, he said he wants to do this without knowing the rest of the slots. 
To redefine the class he needs to know /everything/ about the class. 
granted, the mop can handle that. More important is whether there is an 
easier way to achieve the desired application semantics.

ie, after adding this slot will his code miraculously grow calls to the 
slot accessors? Will the new slot's initform be counted on to be there 
during some reinitialization of the instance?

Speaking of which, I coulda swore I heard him say he wanted to add a 
slot to an instance at some point... how is your prototype hack coming?

:)

kenny
From: Thomas F. Burdick
Subject: Re: adding new slots interactively
Date: 
Message-ID: <xcv8xt4xu24.fsf@conquest.OCF.Berkeley.EDU>
Kenny Tilton <·············@nyc.rr.com> writes:

> Speaking of which, I coulda swore I heard him say he wanted to add a
> slot to an instance at some point... how is your prototype hack coming?
> 
> :)

It works, except for a bug or two, but then Cells II came along, and I
haven't forward-ported it.  (Not going to all that soon, either, I'm
too busy playing with the AltiVec unit in my new G4).

However, it wasn't a full prototype object system, just support for
prototype-based instantiation (I didn't want to give up CLOS!).  That
means MAKE-INSTANCE-FROM-PROTOTYPE (aka make-blast) and
MAKE-INSTANCE-OF-CLASS-FROM-PROTOTYPE (aka make-blast-of-class) where
the specified class and the prototype don't have to match.  So, no
support for addingnew slots to an existing instance, though.

I could extend it to define new classes on the fly so you could do
make-blast and specify slots that don't exist in the prototype.  I
didn't need that for what I used it for, though.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138200372.413891.94380@f14g2000cwb.googlegroups.com>
I need to add a slot dynamically because it is WHAT i need. In that
case, a new attribute was added to an xml document. Since i have
classes which represent xml document structures, i just want to add a
new slot. Evaluating a whole defclass is just a way (HOW) to do that
(bad one).

In fact, evaluating a defclass is just saying to lisp : hey this is the
new definition of my class, check what is different and implement it.
So you have lose information in the process : that you just want to add
a new slot. You are just not telling the same thing to your interpreter.
From: Thomas A. Russ
Subject: Re: adding new slots interactively
Date: 
Message-ID: <ymihd7sf5m3.fsf@sevak.isi.edu>
"ctu" <······@yahoo.com> writes:

> In fact, evaluating a defclass is just saying to lisp : hey this is the
> new definition of my class, check what is different and implement it.
> So you have lose information in the process : that you just want to add
> a new slot. You are just not telling the same thing to your interpreter.

But what sort of information do you lose?
None of the existing instances will lose any of the data in any slots
that remain after the update.  The default behavior of updating
instances when their class is redefined retains all slots that remain
and discards values for slots that go away.  Other behavior is also
possible, but you have to implement it yourself by specializing a
method.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138456203.223798.103760@g43g2000cwa.googlegroups.com>
>> In fact, evaluating a defclass is just saying to lisp : hey this is the
>> new definition of my class, check what is different and implement it.
>> So you have lose information in the process : that you just want to add
>> a new slot. You are just not telling the same thing to your interpreter.

>But what sort of information do you lose?

That the difference is just 1 new slot.

Do you agree that with a new defclass, CLOS will first have to search
the differences to implement them leaving the rest untouched ? with an
add-slot api, clos will just have to do the implemention phase.
From: Pascal Costanza
Subject: Re: adding new slots interactively
Date: 
Message-ID: <441c9fF1ouvh7U1@individual.net>
ctu wrote:

> Do you agree that with a new defclass, CLOS will first have to search
> the differences to implement them leaving the rest untouched ? with an
> add-slot api, clos will just have to do the implemention phase.

Ah, so you expect a simpler implementation if there were an add-slot 
operator? However, it wouldn't actually simplify anything because a slot 
with the same name could be defined in some superclass or subclass, and 
this means that there would still be a phase necessary in which CLOS 
would have to "search the differences".

See 7.5.3 in the HyperSpec for the specification how multiply defined 
slots need to be combined by a CLOS implementation.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Thomas A. Russ
Subject: Re: adding new slots interactively
Date: 
Message-ID: <ymifyncf5jz.fsf@sevak.isi.edu>
"ctu" <······@yahoo.com> writes:

> I need to add a slot dynamically because it is WHAT i need. In that
> case, a new attribute was added to an xml document. Since i have
> classes which represent xml document structures, i just want to add a
> new slot. Evaluating a whole defclass is just a way (HOW) to do that
> (bad one).

So why not just use dynamic slots to implement this?  It isn't really
difficult to implement a dynamic slot system in Lisp.  You could
probably even find an existing implementation in one of the code
repositories.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138456469.348252.119150@g43g2000cwa.googlegroups.com>
> So why not just use dynamic slots to implement this?

Before implementing something by myself, i'm searching if it doesn't
exist.

After asking my question here, it seems that add-slot is not the way to
go with CLOS/MOP, so now i will implement a representation more suited
to my needs.
From: jayessay
Subject: Re: adding new slots interactively
Date: 
Message-ID: <m3d5ig9r4p.fsf@rigel.goldenthreadtech.com>
"ctu" <······@yahoo.com> writes:

> I need to add a slot dynamically because it is WHAT i need. In that
> case, a new attribute was added to an xml document. Since i have
> classes which represent xml document structures, i just want to add a
> new slot.

Do you have a schema definition for this xml?  Are you saying the
schema is changing and that you need to then update to accomodate the
new schema defintions?  Or are you saying something more like, "well,
no, there isn't even a schema definition, the structure is loosely
defined and changes are just made to bits when needed"?

If it is more like the former, then changing the class isn't a "bad
thing", it's exactly the _right_ thing since you are in fact mirroring
the the fact that the analog "type definition" in the .xsd file has
changed its definition.

If you are closer to being in the latter situation, then you probably
don't want classes as your representation primitive.  More likely
something akin to what some people call a "dictionary".


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138208339.521825.266230@f14g2000cwb.googlegroups.com>
We don't use schemas but we could have use them.

Changes arise because specifications are evolving, so are the xml
structure of our document.

In one case, one attribute was added so one slot has to be added.

One thing to note is that changes come from me not from .xsd file. If
we have used schemas, the .xsd should have been generated from the
change not the contrary.
From: jayessay
Subject: Re: adding new slots interactively
Date: 
Message-ID: <m38xt49p8h.fsf@rigel.goldenthreadtech.com>
"ctu" <······@yahoo.com> writes:

> We don't use schemas but we could have use them.
> 
> Changes arise because specifications are evolving, so are the xml
> structure of our document.

Right.  It is all adhoc.  I see this with xml stuff all the time.
Because of this, as I mentioned before, I really think that your major
problem here is that you have picked the wrong representation
primitive - you don't want classes here.


> One thing to note is that changes come from me not from .xsd file. If
> we have used schemas, the .xsd should have been generated from the
> change not the contrary.

_If_ you have xsd, then _it_ should be the primary definition of the
representation.  If it isn't, then having it is a complete waste (not
to mention totally stupid). So, if you have one, you change the xsd
and then "recompile it" (say, by (re)generating all the class
definitions used to represent its content).  Using classes in this
case would be completely reasonable and probably the Right Thing to
do.

But as you say, you don't have a schema and your changes are
completely adhoc, evolving and transient.  This pretty much
guarantees that you don't want to use classes.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138211017.103373.269110@g43g2000cwa.googlegroups.com>
I have picked up the closest representation of concept/relation i know
in lisp : clos. But it seems to be insufficient for what i do.

Taking xsd as representation has one major issue : as you stated, a
change implies a recompilation. If your representation is in lisp, you
can add/remove things without recompiling all.
From: jayessay
Subject: Re: adding new slots interactively
Date: 
Message-ID: <m34q3s9k6y.fsf@rigel.goldenthreadtech.com>
"ctu" <······@yahoo.com> writes:

Please learn to quote - it's not clear who you are responding to or
what you are responding about.


> I have picked up the closest representation of concept/relation i know
> in lisp : clos.

I'm sure you believe this, but in the case you describe you are
_wrong_.  Classes (even CLOS classes!) are not really dynamic enough
to handle this sort of willy-nilly change you describe.  What you
probably want is a simple object type which has _no "schema"_
structure at all (that includes classes which have slot structures).
The properties or fields of which are held in a "dictionary"
(basically a glorified hashtable).


> But it seems to be insufficient for what i do.

It's not "insufficient" its just the _wrong_ tool!


> Taking xsd as representation has one major issue : as you stated, a
> change implies a recompilation.

I don't care if you use an xsd or not.  Not using one isn't
necessarily wrong[1].


> If your representation is in lisp, you can add/remove things without
> recompiling all.

If you pick the _right_ representation things will be fine.  The thing
is, you are trying to pound a square peg into a round hole and then
claiming that the parts don't seem to fit too well.  Well, duh!!


/Jon

1. Your real problem is that you are using xml in the first place.  I
   hope you either had no choice in this and so have to use it or you
   can realize that it is wrong and change it.

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Adrian Kubala
Subject: Re: adding new slots interactively
Date: 
Message-ID: <slrndthks8.pe4.adrian-news@sixfingeredman.net>
On 2006-01-25, ctu <······@yahoo.com> wrote:
> In fact, evaluating a defclass is just saying to lisp : hey this is the
> new definition of my class, check what is different and implement it.
> So you have lose information in the process : that you just want to add
> a new slot. You are just not telling the same thing to your interpreter.

A lot of people find the declarative paradigm easier to understand and
maintain. For example, imagine you have added several new fields which
interact in complicated ways. You could sit there thinking, gosh, did I
enter those fields/methods in the correct order? Or you could just add
them to the class definition, look over it until you're convinced it's
right, and then reload the class. Even better, it doesn't matter if
you're jumping one revision or 10; you don't have to apply a bunch of
patches in the correct order, you just reload the whole changed
definition and it magically does the right thing.

In your case, if you had an XSD, you could write code to automatically
generate stub CLOS classes from the XSD declarations. If the declaration
changes, just rebuild your stubs (maybe as simple as recompiling) and
reload. No fiddling about with diffs.

When I'm working with a SQL schema, I have the exact opposite problem as
you; I only want to maintain one set of declarations for the complete
schema and have it make the necessary changes to the db when I change it
and reload. Of course this won't work so instead I have a bunch of
"update" scripts that are loaded in a special order to introduce
changes, and I add comments in the original schema so that I don't have
to dig through 50 update scripts to find the definition of some
relationship or other.
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138457421.324799.81750@g49g2000cwa.googlegroups.com>
> A lot of people find the declarative paradigm easier to understand and
> maintain. For example, imagine you have added several new fields which
> interact in complicated ways. You could sit there thinking, gosh, did I
> enter those fields/methods in the correct order? Or you could just add
>them to the class definition, look over it until you're convinced it's
>right, and then reload the class. Even better, it doesn't matter if
>you're jumping one revision or 10; you don't have to apply a bunch of
>patches in the correct order, you just reload the whole changed
>definition and it magically does the right thing.

hum, be careful ! i think you have confused 'declarative' with
'all-at-once'

Saying to your lisp to add a new slot is purely declarative if your
goal is just to have this new slot added. You declare WHAT you want and
not HOW to do it.
From: Adrian Kubala
Subject: Re: adding new slots interactively
Date: 
Message-ID: <slrndtvp40.4t3.adrian-news@sixfingeredman.net>
On 2006-01-28, ctu <······@yahoo.com> wrote:
>> A lot of people find the declarative paradigm easier to understand and
>> maintain. For example, imagine you have added several new fields which
>> interact in complicated ways. You could sit there thinking, gosh, did I
>> enter those fields/methods in the correct order? Or you could just add
>>them to the class definition, look over it until you're convinced it's
>>right, and then reload the class. Even better, it doesn't matter if
>>you're jumping one revision or 10; you don't have to apply a bunch of
>>patches in the correct order, you just reload the whole changed
>>definition and it magically does the right thing.
>
> hum, be careful ! i think you have confused 'declarative' with
> 'all-at-once'

Indeed, the opposite of "declarative" is "imperative". A declarative
style does not have any implicit notion of "added", time, or
before-and-after, it simply declares the final form of the solution (in
this case, the final schema of your classes).

> Saying to your lisp to add a new slot is purely declarative if your
> goal is just to have this new slot added.

If this is declarative, then the term is useless -- any program
trivially "declares" what you want the computer to do. But in fact, your
goal is not to add a slot, it's to ensure that the class includes all
the slots needed to run your program. You don't care whether the slot
happens to be already there, or maybe more than one slot is missing, or
maybe the class doesn't even exist; you just want to be sure that the
class exists with all the slots you need.
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138986467.119891.58610@g43g2000cwa.googlegroups.com>
>> hum, be careful ! i think you have confused 'declarative' with
>> 'all-at-once'

>Indeed, the opposite of "declarative" is "imperative".
i agree.

>A declarative style does not have any implicit notion of "added", time, or
>before-and-after, it simply declares the final form of the solution
It's not as simple, declarativity is a relative notion.

((lambda(x) (1+ (1+ x))) P) may be considered declarative if you want
to add 1 two times to P.

It is imperative if you want to add 2 to P.

> (in this case, the final schema of your classes).
wrong, what i want is an added slot not a final schema ( i'm not even
knowing the all schema !). This was my true intention.

>> Saying to your lisp to add a new slot is purely declarative if your
>> goal is just to have this new slot added.

>If this is declarative, then the term is useless -- any program
>trivially "declares" what you want the computer to do.

Of course ! But the problem arises from the fact that we would prefer
languages enabling us to "declare" what we want them to achieve (and
not to do).

> But in fact, your goal is not to add a slot, it's to ensure that the class includes all
>the slots needed to run your program. You don't care whether the slot
>happens to be already there, or maybe more than one slot is missing, or
>maybe the class doesn't even exist; you just want to be sure that the
>class exists with all the slots you need.

Wrong ! at the time i wanted the add-slot api, i know that the class
exists but doesn't have a particular slot. And all i want was this slot
to be added. i didn't care about the other slots.
From: Adrian Kubala
Subject: Re: adding new slots interactively
Date: 
Message-ID: <slrndu7q91.4bi.adrian-news@sixfingeredman.net>
On 2006-02-03, ctu <······@yahoo.com> wrote:
>> But in fact, your goal is not to add a slot, it's to ensure that the class includes all
>>the slots needed to run your program. You don't care whether the slot
>>happens to be already there, or maybe more than one slot is missing, or
>>maybe the class doesn't even exist; you just want to be sure that the
>>class exists with all the slots you need.
>
> Wrong ! at the time i wanted the add-slot api, i know that the class
> exists but doesn't have a particular slot. And all i want was this slot
> to be added. i didn't care about the other slots.

Then you should be happy with this definition of add-slot:

(defmacro add-slot (class slot-definition)
  `(defclass ,class () (,slot-definition)))

(You might argue that this also deletes some other slots, but then, you
don't care about those other slots or even know if they're there, right,
so how can you tell?)
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1139217378.384835.69550@o13g2000cwo.googlegroups.com>
>> Wrong ! at the time i wanted the add-slot api, i know that the class
>> exists but doesn't have a particular slot. And all i want was this slot
>> to be added. i didn't care about the other slots.

>Then you should be happy with this definition of add-slot:

>(defmacro add-slot (class slot-definition)
>  `(defclass ,class () (,slot-definition)))

>(You might argue that this also deletes some other slots, but then, you
>don't care about those other slots or even know if they're there, right,
>so how can you tell?)

The definition you gave is 'ensure this new slot will be present' and
surely not 'ensure this slot is added'. 'Added' implies that all other
slots are still there. So your definition is not an implementation of
the contract.
From: Thomas A. Russ
Subject: Re: [how] adding new slots interactively
Date: 
Message-ID: <ymik6cpf2ot.fsf@sevak.isi.edu>
"ctu" <······@yahoo.com> writes:

> 
> 
> Wondering how i can add a new slot to an existing class ?
> 
> - i just want to add a new slot, not redefining the entire class. It is
> for use in interactive dev.
>   i don't want to re-evaluate the entire class definition.

Well, that is pretty much what you need to do, unless you have access to
the appropriate MOP functions.  Of course, they only let you do the same
thing more programmatically.

> - i look cl & clos api and didn't find the solution. no 'add-slot' ...
> 
> - i found a bad way to do that : using ensure-class and merging with
> the old-definition.

This is the MOP way.  It's effectively the same thing, since you end up
with a redefined class.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: John Thingstad
Subject: Re: [how] adding new slots interactively
Date: 
Message-ID: <op.s3xo22cepqzri1@mjolner.upc.no>
On Tue, 24 Jan 2006 18:01:15 +0100, ctu <······@yahoo.com> wrote:

>
> Wondering how i can add a new slot to an existing class ?
>
> - i just want to add a new slot, not redefining the entire class. It is
> for use in interactive dev.
>   i don't want to re-evaluate the entire class definition.
>
> - i look cl & clos api and didn't find the solution. no 'add-slot' ...
>
> - i found a bad way to do that : using ensure-class and merging with
> the old-definition.
>

Add it to a new class inherit the old one and extend-class.
Unless it is really a attribute of the old claass.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Pascal Costanza
Subject: Re: [how] adding new slots interactively
Date: 
Message-ID: <43se4jF1p9q99U1@individual.net>
ctu wrote:
> Wondering how i can add a new slot to an existing class ?
> 
> - i just want to add a new slot, not redefining the entire class. It is
> for use in interactive dev.
>   i don't want to re-evaluate the entire class definition.
> 
> - i look cl & clos api and didn't find the solution. no 'add-slot' ...
> 
> - i found a bad way to do that : using ensure-class and merging with
> the old-definition.

AspectL contains functions and macros for doing this. There, the concept 
is called "destructive mixins". See 
http://common-lisp.net/project/aspectl/overview.html#mixins for an example.

I haven't updated AspectL in a while because currently, I am focussing 
on ContextL and other things. However, I have started to make AspectL 
use Closer to MOP (a CLOS MOP compatibility layer) so that it gets into 
better shape again. Unfortunately, this revealed some bugs in some CLOS 
MOP implementations that I have to figure out.

See http://common-lisp.net/project/aspectl/release-notes.html for the CL 
implementations on which the current version of AspectL has been tested. 
I cannot guarantee that newer versions of those implementations will 
support AspectL out of the box.

BTW, I think what you want is too hackerish (that's one of the reasons 
why I haven't worked on destructive mixins anymore). ContextL provides a 
cleaner way to define partial classes and have them combined 
automatically (including at runtime). However, I don't know whether it 
suits your needs in this case.

A better way, as other people suggested, would probably be a CLOS 
metaclass that supports storing slots in hashtables - then you can 
arbitrarily add new slots at runtime without even changing class 
definitions.

Pascal


-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Kenny Tilton
Subject: Re: [how] adding new slots interactively
Date: 
Message-ID: <iD9Cf.9387$SD.123@news-wrt-01.rdc-nyc.rr.com>
Pascal Costanza wrote:
> ctu wrote:
> 
>> Wondering how i can add a new slot to an existing class ?
>>
>> - i just want to add a new slot, not redefining the entire class. It is
>> for use in interactive dev.
>>   i don't want to re-evaluate the entire class definition.
>>
>> - i look cl & clos api and didn't find the solution. no 'add-slot' ...
>>
>> - i found a bad way to do that : using ensure-class and merging with
>> the old-definition.
> 
> 
> AspectL contains functions and macros for doing this. There, the concept 
> is called "destructive mixins". See 
> http://common-lisp.net/project/aspectl/overview.html#mixins for an example.
> 
> I haven't updated AspectL in a while because currently, I am focussing 
> on ContextL and other things. However, I have started to make AspectL 
> use Closer to MOP (a CLOS MOP compatibility layer) so that it gets into 
> better shape again. Unfortunately, this revealed some bugs in some CLOS 
> MOP implementations that I have to figure out.
> 
> See http://common-lisp.net/project/aspectl/release-notes.html for the CL 
> implementations on which the current version of AspectL has been tested. 
> I cannot guarantee that newer versions of those implementations will 
> support AspectL out of the box.
> 
> BTW, I think what you want is too hackerish (that's one of the reasons 
> why I haven't worked on destructive mixins anymore). ContextL provides a 
> cleaner way to define partial classes and have them combined 
> automatically (including at runtime). However, I don't know whether it 
> suits your needs in this case.
> 
> A better way, as other people suggested, would probably be a CLOS 
> metaclass that supports storing slots in hashtables - then you can 
> arbitrarily add new slots at runtime without even changing class 
> definitions.

The more I think about it, the less I think the OP wants slots. What 
they want is a way to live with XML data in the face of an unstable 
schema (a rather normal requirement). XML carries meta-data around with 
it, DSD or no, and Lisp loves reflection, metadata, symbolic processing 
etc etc. So the OP was done with the problem when they selected CL, but 
then made the mistake of thinking classes implicit in the data (say, 
Patient, in a clinical trial application) had to be expressed as a named 
  Patient class. Now the wheels are starting to come off. The XML OO 
model differs from the vanilla CLOS model, including a stupid pet trick 
that would require AMOP hacking and non-vanilla CLOS, or implementing a 
homebrew OO (implementing slots as an assoc or hashtable). So now we 
have c.l.l pulling its hair out trying to support the original mistake. 
Why is it a mistake? Well, will the Lisp code include:

    (make-instance 'Patient :surprise 42)

...where surprise is an unexpected slot not known to the application 
until a wodge of XML came flying over the fence? No. Then it would not 
be a surprise. If we can add surprise dynamically, will it have an 
initform? Will subclasses grow:

    :default-initargs :surprise 42

? Nah. Will the surrounding code sprout:

    (surprise this-patient)

..references? More fairly, will the application now be modified here and 
there to use this new slot? Reasonable. When the slot goes away in some 
future refactoring of the clinical data class hierarchy, will the 
resultoing code then spontaneously combust? We can hope.

Maybe I am missing something. It happens. Maybe the OP wants a slick way 
of shifting from Java to CL, or at least doing new work in CL when a big 
Java system still wags the dog. Well, is the dog. So they /do/ want to 
code (make-instance 'Patient) at least, and not fall over (or more 
likely fail to handle) a surprise slot. The Java app will get 
refactored, then what happens to the CL app?

Well, Java has a nice reflection package. Write some Java code to dump 
an XML schema description (DTD?) and then a CL utility to write the 
corresponding CLOS code, qua source so programmers have something to 
look at.

jes' thinkin' out loud.

kenny
From: Pascal Costanza
Subject: Re: [how] adding new slots interactively
Date: 
Message-ID: <43snnjF1pl298U1@individual.net>
Kenny Tilton wrote:
> Why is it a mistake? Well, will the Lisp code include:
> 
>    (make-instance 'Patient :surprise 42)
> 
> ...where surprise is an unexpected slot not known to the application 
> until a wodge of XML came flying over the fence? No. Then it would not 
> be a surprise. If we can add surprise dynamically, will it have an 
> initform? Will subclasses grow:
> 
>    :default-initargs :surprise 42
> 
> ? Nah. Will the surrounding code sprout:
> 
>    (surprise this-patient)
> 
> ..references? More fairly, will the application now be modified here and 
> there to use this new slot? Reasonable. When the slot goes away in some 
> future refactoring of the clinical data class hierarchy, will the 
> resultoing code then spontaneously combust? We can hope.
> 
> Maybe I am missing something. It happens. Maybe the OP wants a slick way 
> of shifting from Java to CL, or at least doing new work in CL when a big 
> Java system still wags the dog. Well, is the dog. So they /do/ want to 
> code (make-instance 'Patient) at least, and not fall over (or more 
> likely fail to handle) a surprise slot. The Java app will get 
> refactored, then what happens to the CL app?
> 
> Well, Java has a nice reflection package. Write some Java code to dump 
> an XML schema description (DTD?) and then a CL utility to write the 
> corresponding CLOS code, qua source so programmers have something to 
> look at.
> 
> jes' thinkin' out loud.

The OP mentioned something about interactive development. So I think 
it's not too bad an idea to do something in between. Like, for example, 
adding a slot on the fly so that the application still runs and doesn't 
just stop with an exception. That additional could be flagged or logged, 
however, so that there is information available for a later refactoring 
step.

Also "jes' thinkin' out loud". (Imagine a thick German accent here... ;)


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Coby Beck
Subject: Re: [how] adding new slots interactively
Date: 
Message-ID: <8daCf.110658$AP5.86238@edtnps84>
"Pascal Costanza" <··@p-cos.net> wrote in message 
····················@individual.net...
> Kenny Tilton wrote:
>> Why is it a mistake? Well, will the Lisp code include:
>>
>>    (make-instance 'Patient :surprise 42)
>>
>> ...where surprise is an unexpected slot not known to the application 
>> until a wodge of XML came flying over the fence? No. Then it would not be 
>> a surprise. If we can add surprise dynamically, will it have an initform? 
>> Will subclasses grow:
>>
>>    :default-initargs :surprise 42
>>
>> ? Nah. Will the surrounding code sprout:
>>
>>    (surprise this-patient)
>>
>> ..references? More fairly, will the application now be modified here and 
>> there to use this new slot? Reasonable. When the slot goes away in some 
>> future refactoring of the clinical data class hierarchy, will the 
>> resultoing code then spontaneously combust? We can hope.
>>
>> Maybe I am missing something. It happens. Maybe the OP wants a slick way 
>> of shifting from Java to CL, or at least doing new work in CL when a big 
>> Java system still wags the dog. Well, is the dog. So they /do/ want to 
>> code (make-instance 'Patient) at least, and not fall over (or more likely 
>> fail to handle) a surprise slot. The Java app will get refactored, then 
>> what happens to the CL app?
>>
>> Well, Java has a nice reflection package. Write some Java code to dump an 
>> XML schema description (DTD?) and then a CL utility to write the 
>> corresponding CLOS code, qua source so programmers have something to look 
>> at.
>>
>> jes' thinkin' out loud.
>
> The OP mentioned something about interactive development. So I think it's 
> not too bad an idea to do something in between. Like, for example, adding 
> a slot on the fly so that the application still runs and doesn't just stop 
> with an exception. That additional could be flagged or logged, however, so 
> that there is information available for a later refactoring step.
>
> Also "jes' thinkin' out loud". (Imagine a thick German accent here... ;)

I was going to mention I thought he had said it was for interactive 
development too.  In which case, why in the world not just go add the slot 
in the source for the class definition and re-evaluate.  No worries about 
forgetting to put it in the right place later either.  Seems like alot of 
trouble to avoid a little trouble, which usually leads to lots more trouble.

Jes' creating pearls of wisdom in real time in public ;)

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: ctu
Subject: Re: adding new slots interactively
Date: 
Message-ID: <1138461934.371017.173120@o13g2000cwo.googlegroups.com>
>I was going to mention I thought he had said it was for interactive
>development too.  In which case, why in the world not just go add the slot
>in the source for the class definition and re-evaluate.  No worries about
>forgetting to put it in the right place later either.  Seems like alot of
>trouble to avoid a little trouble, which usually leads to lots more trouble.

Because i have no defclass definition in the source code ;-) Classes
are created dynamically by the program.

Note that you can view source files differently from the standard point
of view. In general source files are only created by human programmers.
You can also view them as a 'state of your program' that may be loaded
further by other computers or restauration.

ex :

> (defclass toto () ())
> (add-slot 'toto 'att ...)
> (save :project "test")

and it writes a test.lisp file with a canonical representation of its
state :

-- test.lisp --
(defclass toto ()
  (toto ...) )
From: Coby Beck
Subject: Re: adding new slots interactively
Date: 
Message-ID: <LNRCf.154258$km.105984@edtnps89>
"ctu" <······@yahoo.com> wrote in message 
·····························@o13g2000cwo.googlegroups.com...
>>I was going to mention I thought he had said it was for interactive
>>development too.  In which case, why in the world not just go add the slot
>>in the source for the class definition and re-evaluate.  No worries about
>>forgetting to put it in the right place later either.  Seems like alot of
>>trouble to avoid a little trouble, which usually leads to lots more 
>>trouble.
>
> Because i have no defclass definition in the source code ;-) Classes
> are created dynamically by the program.


Aha!  Well, that is a very good reason I did not imagine.

I see in another post you are considering changing your approach, probably a 
good idea.  If you are not specializing methods on these classes, it is 
probably a pretty big hammer for a small data storage nail.

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Michael Price
Subject: Re: [how] adding new slots interactively
Date: 
Message-ID: <slrndtj93m.37k.malus42@yahoo.com>
On 2006-01-26, Pascal Costanza <··@p-cos.net> wrote:
>  Kenny Tilton wrote:
> > 
> > Maybe I am missing something. It happens. Maybe the OP wants a slick way 
> > of shifting from Java to CL, or at least doing new work in CL when a big 
> > Java system still wags the dog. Well, is the dog. So they /do/ want to 
> > code (make-instance 'Patient) at least, and not fall over (or more 
> > likely fail to handle) a surprise slot. The Java app will get 
> > refactored, then what happens to the CL app?
> 
>  The OP mentioned something about interactive development. So I think 
>  it's not too bad an idea to do something in between. Like, for example, 
>  adding a slot on the fly so that the application still runs and doesn't 
>  just stop with an exception. That additional could be flagged or logged, 
>  however, so that there is information available for a later refactoring 
>  step.

I was working on a system once that required some algorithms to operate on
a set of data. I wanted to represent the data in an object-oriented
fashion but due to forces beyond my control the data kept changing during
development. New algorithms were continually added and each needed a
similar but slightly different data model. Changing classes over and over
got old quick.

Like the OP I was bothered by what I perceived to be CLOS's lack of
add-slot. I was also unwise in the ways of MOP and short on time. I
eventually just changed the parser to stick everything into a set of
nested hash tables. For each algorithm I added a verifier function that
made sure the appropriate data for the algorithm you wanted to run was
present and coherent. That ended the endless parser and class
changes. Anytime I wanted to add a new algorithm the parsing and data
storage was already handled. All I had to do was write the verifier
function and the algorithm.

I took the precaution of accessing the hash tables though helper function
that syntactically look like accessor functions. That way I could switch
back to CLOS with minimal (if any) changes to the algorithm code. The
nested hash-table approach is working out so well though that I'm not sure
if I want to change it.

Michael