From: Pascal Costanza on
On 30/06/2010 04:05, Scott L. Burson wrote:
> On Jun 28, 11:58 pm, Christophe Rhodes<cs...(a)cantab.net> wrote:
>> "Scott L. Burson"<g...(a)zeta-soft.com> writes:
>>
>>> On Jun 28, 12:09 am, Pascal Costanza<p...(a)p-cos.net> wrote:
>>>> On 28/06/2010 01:00, Scott L. Burson wrote:
>>
>>>>> For those with more MOP experience than I, what's the easiest way to
>>>>> programmatically add a slot to an existing class?
>>
>>>> The situations were you may want to do this are usually extremely rare.
>>>> So it may be useful to tell us what you want to achieve, so we can maybe
>>>> come up with better solutions.
>>
>>> I just wanted to extend a class whose definition I don't control. I
>>> could just load a patch containing the DEFCLASS form with my slot
>>> added -- I do have access to the original DEFCLASS form -- but then if
>>> it changed, I would have to update my patch. Doing it this way makes
>>> it reasonably upgrade-proof.
>>
>> For what it's worth: I'd be tempted to add in a superclass mixin
>> containing your slot, rather than patch in the slot directly; the effect
>> is basically the same, but maybe marginally more upgrade-proof?
>
> I don't see offhand how it would be any more upgrade-proof.
>
>> However, is this not a sign that something somewhere else isn't quite
>> right? The "normal" way to do this would be to arrange that you use a
>> subclass of the original class, creating instances of that class and
>> passing them around
>
> In this particular case, that wouldn't be hard. In general, though,
> it can be more difficult.
>
> I think a program organization that allows slot definitions to appear
> in various locations in the source code could be described as aspect-
> oriented rather than object-oriented. (I faintly recall that AspectJ
> (which I have never used but heard a talk about once) has a way to add
> a slot to a class.) I think it's a valid and sometimes useful way of
> organizing code, despite the fact that it seems strange and wrong to
> people used to object-oriented organization.

Ah, if you want to do this in a AOP-style, you can actually use ContextL:

(define-layered-class person ()
((name :initarg :name :reader person-name)))

(deflayer additional-slots)

(define-layered-class person :in-layer additional-slots ()
((address :initarg :address :reader person-address)))

etc.

You can add as many layers as you want (you would usually use more
declarative names). The typical use case is to use dynamically scoped
layer activation, but you can also activate layers globally via
'ensure-active-layer. (Partial) class definitions will be composed into
the running system, and all existing instances of adapted classes will
be updated.

This is less dynamic than what Rainer shows in his video, for example,
but a lot more dynamic than plain CLOS.


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: Scott L. Burson on
On Jul 2, 3:47 am, Pascal Costanza <p...(a)p-cos.net> wrote:
> On 30/06/2010 04:05, Scott L. Burson wrote:
>
>
>
> > On Jun 28, 11:58 pm, Christophe Rhodes<cs...(a)cantab.net>  wrote:
> >> "Scott L. Burson"<g...(a)zeta-soft.com>  writes:
>
> >>> On Jun 28, 12:09 am, Pascal Costanza<p...(a)p-cos.net>  wrote:
> >>>> On 28/06/2010 01:00, Scott L. Burson wrote:
>
> >>>>> For those with more MOP experience than I, what's the easiest way to
> >>>>> programmatically add a slot to an existing class?
>
> >>>> The situations were you may want to do this are usually extremely rare.
> >>>> So it may be useful to tell us what you want to achieve, so we can maybe
> >>>> come up with better solutions.
>
> >>> I just wanted to extend a class whose definition I don't control.  I
> >>> could just load a patch containing the DEFCLASS form with my slot
> >>> added -- I do have access to the original DEFCLASS form -- but then if
> >>> it changed, I would have to update my patch.  Doing it this way makes
> >>> it reasonably upgrade-proof.
>
> >> For what it's worth: I'd be tempted to add in a superclass mixin
> >> containing your slot, rather than patch in the slot directly; the effect
> >> is basically the same, but maybe marginally more upgrade-proof?
>
> > I don't see offhand how it would be any more upgrade-proof.
>
> >> However, is this not a sign that something somewhere else isn't quite
> >> right?  The "normal" way to do this would be to arrange that you use a
> >> subclass of the original class, creating instances of that class and
> >> passing them around
>
> > In this particular case, that wouldn't be hard.  In general, though,
> > it can be more difficult.
>
> > I think a program organization that allows slot definitions to appear
> > in various locations in the source code could be described as aspect-
> > oriented rather than object-oriented.  (I faintly recall that AspectJ
> > (which I have never used but heard a talk about once) has a way to add
> > a slot to a class.)  I think it's a valid and sometimes useful way of
> > organizing code, despite the fact that it seems strange and wrong to
> > people used to object-oriented organization.
>
> Ah, if you want to do this in a AOP-style, you can actually use ContextL:
>
> (define-layered-class person ()
>    ((name :initarg :name :reader person-name)))
>
> (deflayer additional-slots)
>
> (define-layered-class person :in-layer additional-slots ()
>    ((address :initarg :address :reader person-address)))
>
> etc.
>
> You can add as many layers as you want (you would usually use more
> declarative names). The typical use case is to use dynamically scoped
> layer activation, but you can also activate layers globally via
> 'ensure-active-layer. (Partial) class definitions will be composed into
> the running system, and all existing instances of adapted classes will
> be updated.

Cool! I'm glad to know this, though it doesn't help with this
particular case since I don't control the original DEFCLASS form. But
I will take a look at ContextL for other uses.

-- Scott