From: Saurabh Nanda
Subject: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <fb3tb5$10k$1@registered.motzarella.org>
After a class has been defined (and finalized) using the defclass macro, 
I want to add a slot to it. How can I do it using MOP?

I'm on Allegro CL so code specific of ACL will be okay too.

Thanks,
Saurabh.

From: Pascal Costanza
Subject: Re: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <5jlpjoF81ioU1@mid.individual.net>
Saurabh Nanda wrote:
> After a class has been defined (and finalized) using the defclass macro, 
> I want to add a slot to it. How can I do it using MOP?
> 
> I'm on Allegro CL so code specific of ACL will be okay too.

It can be done using ContextL:

(define-layered-class c ()
   (a b c))

(deflayer more-slots)

(define-layered-class c :in-layer more-slots ()
   (d))

(ensure-active-layer 'more-slots)



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: Saurabh Nanda
Subject: Re: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <fb4fbb$is$2@registered.motzarella.org>
> It can be done using ContextL:

Thanks for the pointer Pascal. Two reasons why I wouldn't particularly 
like to use this solutions:

a) I want to know how to exactly do this in MOP. A learning exercise.
b) I don't want to depend on ContextL for just one teeny little thing.

Please could you tell me how to exactly do this in MOP. Which functions 
should I be looking up?

Saurabh.
From: Pascal Costanza
Subject: Re: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <5jlu98F8sdmU1@mid.individual.net>
Saurabh Nanda wrote:
>> It can be done using ContextL:
> 
> Thanks for the pointer Pascal. Two reasons why I wouldn't particularly 
> like to use this solutions:
> 
> a) I want to know how to exactly do this in MOP. A learning exercise.
> b) I don't want to depend on ContextL for just one teeny little thing.
> 
> Please could you tell me how to exactly do this in MOP. Which functions 
> should I be looking up?

You can find a brute force way to do this in AspectL. It has a concept 
of "destructive mixins" - basically commands to manipulate class 
objects. The general idea is to use the metaobject readers 
(class-direct-slots, slot-definition-name, etc. pp.) to determine the 
current definition of a class, and then to use reinitialize-instance on 
the same class object to redefine it destructively.

That is a pretty gross and unreliable way to change class definitions. 
If you get a parameter to one of the AspectL functions wrong, it is 
quite likely that your system becomes unusable. That's the main reason 
why I discontinued AspectL. I could have added some parameter checking, 
but that would have been a lot of work, and I am convinced that ContextL 
gives you much cleaner abstractions to essentially achieve the same.

Nevertheless, taking a look at the AspectL code may give you some ideas 
how to do what you want (although, to stress it again, I don't recommend 
to do it that way).

In ContextL, the idea is different: Here a layered class always consists 
of a stub class with a list of multiple direct superclasses which 
contain the actual (layered) definitions. Whenever a 
define-layered-class form is evaluated for a new layer, you actually get 
a new direct superclass for the given class that corresponds to the 
definitions for that layer. Mixing the different definitions from the 
different layers is then straightforward - I just rely on standard CLOS 
inheritance (which also gives me very efficient effective classes and 
slots).

You could do the same in your code: For each view-class, actually create 
a stub class that inherits from a view-class and an assocation-class. A 
def-view-class then manipulates the view-class part, and a 
defassociation manipulates the association part.

Or you use ContextL. ;)


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: Saurabh Nanda
Subject: Re: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <fb4inj$did$1@registered.motzarella.org>
>  The general idea is to use the metaobject readers
> (class-direct-slots, slot-definition-name, etc. pp.) to determine the 
> current definition of a class, and then to use reinitialize-instance on 
> the same class object to redefine it destructively.

I'm giving this method a shot for starters. I've hit a roadblock rather 
prematurely. Why is the third form giving me a nil?

(defclass test-class ()
   ((name
     :initarg :name
     :initform "test name"
     :accessor name)))
(finalize-inheritance (find-class 'test-class))
(class-default-initargs (find-class 'test-class))


Saurabh.
From: Geoff Wozniak
Subject: Re: How do I add an extra slot to a class?
Date: 
Message-ID: <1188417545.568377.85430@y42g2000hsy.googlegroups.com>
On Aug 29, 3:51 pm, Saurabh Nanda <············@gmail.com> wrote:
> Why is the third form giving me a nil?
>
> (defclass test-class ()
>    ((name
>      :initarg :name
>      :initform "test name"
>      :accessor name)))
> (finalize-inheritance (find-class 'test-class))
> (class-default-initargs (find-class 'test-class))
>

:DEFAULT-INITARGS are not the same as the :INITARG forms passed to
slots in DEFCLASS.  See section 7.1 in the HyperSpec for a
clarification.
From: Saurabh Nanda
Subject: Re: How do I add an extra slot to a class?
Date: 
Message-ID: <fb4k46$hut$1@registered.motzarella.org>
> :DEFAULT-INITARGS are not the same as the :INITARG forms passed to
> slots in DEFCLASS.  See section 7.1 in the HyperSpec for a
> clarification.

Sorry my goof up. So I guess I'll have to use class-slots to get all the 
slots of the class. For each slot I will have to use 
slot-definition-initargs, slot-definition-readers, 
slot-definition-writers, etc. to get the various slot options. Using all 
this info I'll have to construct the lambda list for 
reinitialize-instance and call it for the class in question.

Wow! Why isn't there a simple macro for this already!

Saurabh.
From: Pascal Costanza
Subject: Re: How do I add an extra slot to a class?
Date: 
Message-ID: <5jm2tiF92l2U1@mid.individual.net>
Saurabh Nanda wrote:
>> :DEFAULT-INITARGS are not the same as the :INITARG forms passed to
>> slots in DEFCLASS.  See section 7.1 in the HyperSpec for a
>> clarification.
> 
> Sorry my goof up. So I guess I'll have to use class-slots to get all the 
> slots of the class. For each slot I will have to use 
> slot-definition-initargs, slot-definition-readers, 
> slot-definition-writers, etc. to get the various slot options. Using all 
> this info I'll have to construct the lambda list for 
> reinitialize-instance and call it for the class in question.
> 
> Wow! Why isn't there a simple macro for this already!

I had to learn this the hard way - this is exactly what I originally did 
in AspectL, and it's wrong (to give the executive summary here ;).

You're walking on very thin ice here, and you seem to be using a 
try-and-error approach. You should, at least, first read the Concepts 
chapter of the CLOS MOP specification and understand the essentials of 
MOP programing before proceeding. (No, you don't use the class-slots 
here, but the class-direct-slots, and by reading the Concepts chapter, 
such things, and others, should become clear to you.)

It would be even better to get a copy of AMOP and read it. It's an 
excellent and very insightful book (one of the best computer science 
books according to Alan Kay). There is a reason why the CLOS MOP doesn't 
support class definition by way of setter functions or 
reinitialize-instance that well, and the reason is given there.


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: Saurabh Nanda
Subject: Re: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <fb4fsn$36e$1@registered.motzarella.org>
> Thanks for the pointer Pascal. Two reasons why I wouldn't particularly 
> like to use this solutions:
> 
> a) I want to know how to exactly do this in MOP. A learning exercise.
> b) I don't want to depend on ContextL for just one teeny little thing.

I'm reading through your ContextL paper right now 
(http://p-cos.net/documents/contextl-overview.pdf). I won't be able to 
use this solution because, along with standard-db-class, it will 
introduce another metaclass, layered-class, to deal with.

Saurabh.
From: Pascal Costanza
Subject: Re: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <5jludjF8sdmU2@mid.individual.net>
Saurabh Nanda wrote:
>> Thanks for the pointer Pascal. Two reasons why I wouldn't particularly 
>> like to use this solutions:
>>
>> a) I want to know how to exactly do this in MOP. A learning exercise.
>> b) I don't want to depend on ContextL for just one teeny little thing.
> 
> I'm reading through your ContextL paper right now 
> (http://p-cos.net/documents/contextl-overview.pdf). I won't be able to 
> use this solution because, along with standard-db-class, it will 
> introduce another metaclass, layered-class, to deal with.

OK, that could indeed be a problem. I have discussed this some time ago 
with someone else, and in principle I think it should be possible to 
compose the two metaclasses, but since nobody has actually done that 
yet, I am not sure whether this may yield unexpected problems.


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: Saurabh Nanda
Subject: Re: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <fb4f7j$is$1@registered.motzarella.org>
> Any reason why re-evaluating the defclass form (edited to include the
> new slot definition) won't work for you?

I'm writing a "defassociation" macro for CLSQL to make defining class 
associations more easier. So, after defining various view-classes 
(classes mapped to a tables) one can use the defassociation macro to 
define associations (has-one, has-many, has-and-belongs-to-many) between 
them. This macro will have to add new slots to hold the 
associated/joined objects in the classes participating in the association.

This is why I can't re-evaluate the defclass form (or def-view-class 
form to be more specific) to include the new slot definitions.

Saurabh.
From: Madhu
Subject: Re: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <m37indn37d.fsf@robolove.meer.net>
* Saurabh Nanda <···········@registered.motzarella.org> :
|> Any reason why re-evaluating the defclass form (edited to include the
|> new slot definition) won't work for you?
|
| I'm writing a "defassociation" macro for CLSQL to make defining class
| associations more easier. So, after defining various view-classes
| (classes mapped to a tables) one can use the defassociation macro to
| define associations (has-one, has-many, has-and-belongs-to-many)
| between them. This macro will have to add new slots to hold the
| associated/joined objects in the classes participating in the
| association.
|
| This is why I can't re-evaluate the defclass form (or def-view-class
| form to be more specific) to include the new slot definitions.

That would explain it :) I found the CL-SQL view-class abstraction has
limitations, (as you may have also found), I tried unsuccessfully to use
it for a database-table-designer application.  I ended up modelling the
database relationships and tables in my own CLOS objects, and then had
methods for generating the def-view-class form. (I haven't finished this
to my satisfaction -- still separatating a table class from a sub-class
with the join slots)

Another thing I wanted to do was: given a view-class object, introspect
the join slots and figure out the relations.  The key thing is to have a
representation for the relations that your program (not just CL-SQL) can
access and use at runtime. This could not be done with view-class
across sql + lisp implementation combinations. (I use clsql and ysql,
and would like to use commonsql too).  Also I couldn't mixin objects of
other other types with any ease which would make sense.

I'd be interested in knowing how end up solving this, or if I'm
incorrect in any of my assessments above
--
Madhu
From: Saurabh Nanda
Subject: Re: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <fb5r6i$mrq$1@registered.motzarella.org>
> That would explain it :) I found the CL-SQL view-class abstraction has
> limitations, (as you may have also found), I tried unsuccessfully to use
> it for a database-table-designer application.  I ended up modelling the
> database relationships and tables in my own CLOS objects, and then had
> methods for generating the def-view-class form. (I haven't finished this
> to my satisfaction -- still separatating a table class from a sub-class
> with the join slots)

Apart from the limitations in def-view-class, I've found that CLSQL 
lacks lots of features. For example, the limit and offset arguments to 
the select function do not work for Oracle (Oracle has a weird way to 
get this done, which requires some obtuse subselects). Another one is 
that, pre-fetching immediate join slots is broken (I've fixed this one, 
and am about to release a patch).

> Another thing I wanted to do was: given a view-class object, introspect
> the join slots and figure out the relations.  The key thing is to have a
> representation for the relations that your program (not just CL-SQL) can
> access and use at runtime. This could not be done with view-class
> across sql + lisp implementation combinations. (I use clsql and ysql,
> and would like to use commonsql too).  

I'm not sure I understood what you're trying to do here. Can you 
elaborate a bit?


> Also I couldn't mixin objects of
> other other types with any ease which would make sense.

I've tried mixing Allegro's persistent metaclass and CLSQL's 
standard-db-class to be able to store an object either in the DB or the 
acache. I failed miserably.

Saurabh.
From: Madhu
Subject: Re: [MOP] How do I add an extra slot to a class?
Date: 
Message-ID: <m3lkbtl43z.fsf@robolove.meer.net>
* Saurabh Nanda <············@registered.motzarella.org> :
|> Another thing I wanted to do was: given a view-class object, introspect
|> the join slots and figure out the relations.  The key thing is to have a
|> representation for the relations that your program (not just CL-SQL) can
|> access and use at runtime. This could not be done with view-class
|> across sql + lisp implementation combinations. (I use clsql and ysql,
|> and would like to use commonsql too).
|
| I'm not sure I understood what you're trying to do here. Can you
| elaborate a bit?

Just that.  Imagine you don't know the columns (slot names) upfront.
Now the descriptions of relations are specified by the db-kind and
db-info arguments to def-view-class.  I was making the case for this
information to be available at runtime, given just a view-class object.

One application, if this were possible, is to say, write "generic" code
for presentation and input methods for database objects for a specific
application, which can be called at runtime, and which takes advantage
of standard clos modeling.  A lot of this would otherwise be just boiler
plate db access and presentation code which needs to be filled in with
correct slot names, and which cannot use OO (to capture the common
behaviour.)  Maybe this is clearer?

--
Madhu