From: vttoonses
Subject: Another MOP Question
Date: 
Message-ID: <3a166e42-6772-41ab-b57c-7c435c90c2e0@s50g2000hsb.googlegroups.com>
First, I'd like to thank everyone who responded to my earlier post. I
was able to resolve the metaclass definition issue by upgrading the
version of lisp I was using (apparently the one that comes with
LispBox is broken).

Since that thread has migrated on to a new subject (XMLisp), I thought
I'd start a new one to ask for more assistance.

I've defined some classes and methods as follows:

;;; - Start

(defclass xml-metalevel-class (standard-class)
  ())

(defclass xml-standard-direct-slot-definition (standard-direct-slot-
definition)
  ((xml-item-type :initform "node" :initarg :xml-item-type :accessor
xml-item-type)))

(defclass xml-standard-effective-slot-definition (standard-effective-
slot-definition)
  ((xml-item-type :initform "node" :initarg :xml-item-type :accessor
xml-item-type)))

(defmethod direct-slot-definition-class ((class xml-metalevel-class)
&rest initargs)
  (declare (ignore initargs))
  (find-class 'xml-standard-direct-slot-definition))

(defmethod effective-slot-definition-class ((class xml-metalevel-
class) &rest initargs)
  (declare (ignore initargs))
  (find-class 'xml-standard-effective-slot-definition))

;;; - End

If I then create a class using xml-metalevel-class like so:
(defclass foo ()
   ((bar :initarg :b :accessor bar :xml-item-type "text"))
   (:metaclass xml-metalevel-class))

and get the resulting class's slot list:
(setf *slts* (class-slots (find-class 'foo)))

and query the first slot for its xml-item-type:
(xml-item-type (car *slts*))

the resulting value is the default ("node") and not the specified
value ("text"). Checking the name of the slot returns "bar" so I'm
relatively sure I'm dealing with the appropriate slot object. Setf'ing
the xml-item-type of the slot and re querying it returns the new
value, so access to the slot's slot does not seem to be impaired.

Can anyone point me in the right direction to resolve this? Thanks,
Gene

From: vttoonses
Subject: Re: Another MOP Question
Date: 
Message-ID: <a9f36725-5904-44ed-98c5-4409890117c7@r66g2000hsg.googlegroups.com>
On Sep 17, 11:35 am, vttoonses <·········@gmail.com> wrote:
> First, I'd like to thank everyone who responded to my earlier post. I
> was able to resolve the metaclass definition issue by upgrading the
> version of lisp I was using (apparently the one that comes with
> LispBox is broken).
>
> Since that thread has migrated on to a new subject (XMLisp), I thought
> I'd start a new one to ask for more assistance.
>
> I've defined some classes and methods as follows:
>
> ;;; - Start
>
> (defclass xml-metalevel-class (standard-class)
>   ())
>
> (defclass xml-standard-direct-slot-definition (standard-direct-slot-
> definition)
>   ((xml-item-type :initform "node" :initarg :xml-item-type :accessor
> xml-item-type)))
>
> (defclass xml-standard-effective-slot-definition (standard-effective-
> slot-definition)
>   ((xml-item-type :initform "node" :initarg :xml-item-type :accessor
> xml-item-type)))
>
> (defmethod direct-slot-definition-class ((class xml-metalevel-class)
> &rest initargs)
>   (declare (ignore initargs))
>   (find-class 'xml-standard-direct-slot-definition))
>
> (defmethod effective-slot-definition-class ((class xml-metalevel-
> class) &rest initargs)
>   (declare (ignore initargs))
>   (find-class 'xml-standard-effective-slot-definition))
>
> ;;; - End
>
> If I then create a class using xml-metalevel-class like so:
> (defclass foo ()
>    ((bar :initarg :b :accessor bar :xml-item-type "text"))
>    (:metaclass xml-metalevel-class))
>
> and get the resulting class's slot list:
> (setf *slts* (class-slots (find-class 'foo)))
>
> and query the first slot for its xml-item-type:
> (xml-item-type (car *slts*))
>
> the resulting value is the default ("node") and not the specified
> value ("text"). Checking the name of the slot returns "bar" so I'm
> relatively sure I'm dealing with the appropriate slot object. Setf'ing
> the xml-item-type of the slot and re querying it returns the new
> value, so access to the slot's slot does not seem to be impaired.
>
> Can anyone point me in the right direction to resolve this? Thanks,
> Gene

After some experimentation, if I get the resulting class's direct
slots:
(setf *dslts* (class-direct-slots (find-class 'foo)))

and query for the xml-item-type, I get the correct value ("text").
"class-slots" returns the effective slots which do not appear to be
initialized from the class definition.

Gene

PS - Just found this in "User Level Language Crafting"
"After the appropriate direct slot definition metaobject has been
created and initialized for each slot specified in the defclass, the
list is kept with the metaobject so that class­-direct­slots can
retrieve and return it."

Doh!
From: Pascal Costanza
Subject: Re: Another MOP Question
Date: 
Message-ID: <6jcnjdF2k7nbU1@mid.individual.net>
vttoonses wrote:
> First, I'd like to thank everyone who responded to my earlier post. I
> was able to resolve the metaclass definition issue by upgrading the
> version of lisp I was using (apparently the one that comes with
> LispBox is broken).
> 
> Since that thread has migrated on to a new subject (XMLisp), I thought
> I'd start a new one to ask for more assistance.
> 
> I've defined some classes and methods as follows:
> 
> ;;; - Start
> 
> (defclass xml-metalevel-class (standard-class)
>   ())
> 
> (defclass xml-standard-direct-slot-definition (standard-direct-slot-
> definition)
>   ((xml-item-type :initform "node" :initarg :xml-item-type :accessor
> xml-item-type)))
> 
> (defclass xml-standard-effective-slot-definition (standard-effective-
> slot-definition)
>   ((xml-item-type :initform "node" :initarg :xml-item-type :accessor
> xml-item-type)))
> 
> (defmethod direct-slot-definition-class ((class xml-metalevel-class)
> &rest initargs)
>   (declare (ignore initargs))
>   (find-class 'xml-standard-direct-slot-definition))
> 
> (defmethod effective-slot-definition-class ((class xml-metalevel-
> class) &rest initargs)
>   (declare (ignore initargs))
>   (find-class 'xml-standard-effective-slot-definition))
> 
> ;;; - End
> 
> If I then create a class using xml-metalevel-class like so:
> (defclass foo ()
>    ((bar :initarg :b :accessor bar :xml-item-type "text"))
>    (:metaclass xml-metalevel-class))
> 
> and get the resulting class's slot list:
> (setf *slts* (class-slots (find-class 'foo)))
> 
> and query the first slot for its xml-item-type:
> (xml-item-type (car *slts*))
> 
> the resulting value is the default ("node") and not the specified
> value ("text"). Checking the name of the slot returns "bar" so I'm
> relatively sure I'm dealing with the appropriate slot object. Setf'ing
> the xml-item-type of the slot and re querying it returns the new
> value, so access to the slot's slot does not seem to be impaired.
> 
> Can anyone point me in the right direction to resolve this?

If you check the values for class-direct-slots instead of class-slots, 
you will see the values you expect. The problem is that you haven't 
taken care yet of copying the values from the direct slots to the 
effective slots. You have to do that yourself.

You can do that in compute-effective-slot-definition, where you can see 
all the direct slot definitions that contribute to the effective slot. 
This also explains why this cannot be done automagically: There may be 
several direct slots with the same name, and they may have different 
values here, so you have to provide some explicit resolution rule to 
deal with this.


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: vttoonses
Subject: Re: Another MOP Question
Date: 
Message-ID: <445a3dd5-ea09-4f18-82c2-157f8f74ba60@b1g2000hsg.googlegroups.com>
On Sep 17, 11:55 am, Pascal Costanza <····@p-cos.net> wrote:
> vttoonses wrote:
> > First, I'd like to thank everyone who responded to my earlier post. I
> > was able to resolve the metaclass definition issue by upgrading the
> > version of lisp I was using (apparently the one that comes with
> > LispBox is broken).
>
> > Since that thread has migrated on to a new subject (XMLisp), I thought
> > I'd start a new one to ask for more assistance.
>
> > I've defined some classes and methods as follows:
>
> > ;;; - Start
>
> > (defclass xml-metalevel-class (standard-class)
> >   ())
>
> > (defclass xml-standard-direct-slot-definition (standard-direct-slot-
> > definition)
> >   ((xml-item-type :initform "node" :initarg :xml-item-type :accessor
> > xml-item-type)))
>
> > (defclass xml-standard-effective-slot-definition (standard-effective-
> > slot-definition)
> >   ((xml-item-type :initform "node" :initarg :xml-item-type :accessor
> > xml-item-type)))
>
> > (defmethod direct-slot-definition-class ((class xml-metalevel-class)
> > &rest initargs)
> >   (declare (ignore initargs))
> >   (find-class 'xml-standard-direct-slot-definition))
>
> > (defmethod effective-slot-definition-class ((class xml-metalevel-
> > class) &rest initargs)
> >   (declare (ignore initargs))
> >   (find-class 'xml-standard-effective-slot-definition))
>
> > ;;; - End
>
> > If I then create a class using xml-metalevel-class like so:
> > (defclass foo ()
> >    ((bar :initarg :b :accessor bar :xml-item-type "text"))
> >    (:metaclass xml-metalevel-class))
>
> > and get the resulting class's slot list:
> > (setf *slts* (class-slots (find-class 'foo)))
>
> > and query the first slot for its xml-item-type:
> > (xml-item-type (car *slts*))
>
> > the resulting value is the default ("node") and not the specified
> > value ("text"). Checking the name of the slot returns "bar" so I'm
> > relatively sure I'm dealing with the appropriate slot object. Setf'ing
> > the xml-item-type of the slot and re querying it returns the new
> > value, so access to the slot's slot does not seem to be impaired.
>
> > Can anyone point me in the right direction to resolve this?
>
> If you check the values for class-direct-slots instead of class-slots,
> you will see the values you expect. The problem is that you haven't
> taken care yet of copying the values from the direct slots to the
> effective slots. You have to do that yourself.
>
> You can do that in compute-effective-slot-definition, where you can see
> all the direct slot definitions that contribute to the effective slot.
> This also explains why this cannot be done automagically: There may be
> several direct slots with the same name, and they may have different
> values here, so you have to provide some explicit resolution rule to
> deal with this.
>
> 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/

Thanks. I looked up compute-effective-slot-definition in "The Art ..."
and found out what I needed to do. The only gotcha is that the current
implementations seem to have an extra parameter (name). I am now
getting the data I need. The question now is whether to write my own
library or use XMLisp. I like the idea of being able to specify
marshalling information with the class definition (ala java
annotations), but I wonder if I am trying to impose an improper
thought/development process on this problem. Am I not thinking in a
"lispy" way?
From: Pascal Costanza
Subject: Re: Another MOP Question
Date: 
Message-ID: <6jdbokF2p15qU1@mid.individual.net>
vttoonses wrote:

> I looked up compute-effective-slot-definition in "The Art ..."
> and found out what I needed to do. The only gotcha is that the current
> implementations seem to have an extra parameter (name).

That's actually also in the CLOS MOP specification, so no 
incompatibilities there. See http://www.lisp.org/mop/

> I am now
> getting the data I need. The question now is whether to write my own
> library or use XMLisp.

It depends. If you do this to get some work done, it's probably better 
to use XMLisp because it seems quite mature. If you want to learn how to 
program meta-level stuff, doing this yourself cold get you some good 
experience with that. It all depends on your goals.

> I like the idea of being able to specify
> marshalling information with the class definition (ala java
> annotations), but I wonder if I am trying to impose an improper
> thought/development process on this problem. Am I not thinking in a
> "lispy" way?

Java has this notion of 'transient' fields which was supposed to allow 
you to declare which fields get serialized and which don't. That was 
never really used, but I think that's the right approach, because it 
gives you a declarative way of defining which slots should be handled in 
which way.

What is wrong in Java is this approach that every class has to define 
its serialization / clone method. That is clearly meta-level 
functionality and it shouldn't be necessary to replicate for each and 
every class. But that's because Java's so-called "Reflection API" is 
quite poor, you cannot do a lot with that...

Arthur Lemmens once gave a very good summary of the possibilities to add 
persistence to Common Lisp. See 
http://www.pentaside.org/paper/persistence-lemmens.txt for the very 
informative write-up.


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: vttoonses
Subject: Re: Another MOP Question
Date: 
Message-ID: <ed9172b2-5ce1-412e-86a5-e676586b6122@k30g2000hse.googlegroups.com>
On Sep 17, 5:39 pm, Pascal Costanza <····@p-cos.net> wrote:
> vttoonses wrote:
> > I looked up compute-effective-slot-definition in "The Art ..."
> > and found out what I needed to do. The only gotcha is that the current
> > implementations seem to have an extra parameter (name).
>
> That's actually also in the CLOS MOP specification, so no
> incompatibilities there. Seehttp://www.lisp.org/mop/
>
> > I am now
> > getting the data I need. The question now is whether to write my own
> > library or use XMLisp.
>
> It depends. If you do this to get some work done, it's probably better
> to use XMLisp because it seems quite mature. If you want to learn how to
> program meta-level stuff, doing this yourself cold get you some good
> experience with that. It all depends on your goals.
>
> > I like the idea of being able to specify
> > marshalling information with the class definition (ala java
> > annotations), but I wonder if I am trying to impose an improper
> > thought/development process on this problem. Am I not thinking in a
> > "lispy" way?
>
> Java has this notion of 'transient' fields which was supposed to allow
> you to declare which fields get serialized and which don't. That was
> never really used, but I think that's the right approach, because it
> gives you a declarative way of defining which slots should be handled in
> which way.
>
> What is wrong in Java is this approach that every class has to define
> its serialization / clone method. That is clearly meta-level
> functionality and it shouldn't be necessary to replicate for each and
> every class. But that's because Java's so-called "Reflection API" is
> quite poor, you cannot do a lot with that...
>
> Arthur Lemmens once gave a very good summary of the possibilities to add
> persistence to Common Lisp. Seehttp://www.pentaside.org/paper/persistence-lemmens.txtfor the very
> informative write-up.
>
> 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/

New problem - I've defined some constants to represent the different
xml item types (attribute, node, etc). When I create a class based on
my metaclass and pass one of these constants as the :xml-item-type
slot data, it is storing the constant's symbol and not its value.

ex.
(defclass test ()
  ((attr1 :initform "attr1 value" :initarg :a1 :accessor :a1 :xml-item-
type +attribute-item-type+))
  (:metaclass xml-metalevel-class))

(setf *slts* (class-slots (find-class 'test)))

(xml-item-type (car *slts*))                                ==>
+ATTRIBUTE-ITEM-TYPE+
+attribute-item-type+                                       ==> 1
(eql (xml-item-type (car *slts*)) +attribute-item-type+)    ==> nil

There's probably a step in the initialization of the class slots that
I need to override to evaluate the form passed in, correct?

Thanks for any help,
Gene
From: Pascal Costanza
Subject: Re: Another MOP Question
Date: 
Message-ID: <6jfh56F33nhgU1@mid.individual.net>
vttoonses wrote:

> New problem -

It's better to start a new discussion thread when you have a new problem.

> I've defined some constants to represent the different
> xml item types (attribute, node, etc). When I create a class based on
> my metaclass and pass one of these constants as the :xml-item-type
> slot data, it is storing the constant's symbol and not its value.
> 
> ex.
> (defclass test ()
>   ((attr1 :initform "attr1 value" :initarg :a1 :accessor :a1 :xml-item-
> type +attribute-item-type+))
>   (:metaclass xml-metalevel-class))
> 
> (setf *slts* (class-slots (find-class 'test)))
> 
> (xml-item-type (car *slts*))                                ==>
> +ATTRIBUTE-ITEM-TYPE+
> +attribute-item-type+                                       ==> 1
> (eql (xml-item-type (car *slts*)) +attribute-item-type+)    ==> nil
> 
> There's probably a step in the initialization of the class slots that
> I need to override to evaluate the form passed in, correct?

There is indeed a step in the initialization of slot definition 
metaobjects that turns initforms into initfunctions which close over the 
correct lexical environment and can be funcalled to yield the correct 
initialization values. However, that step of converting initforms into 
initfunctions is not generalized and not exposed in the CLOS MOP 
specification, so you cannot reuse it portably for your own metaclasses.

LispWorks adds to the CLOS MOP in this respect and provides a protocol 
here, so you could use that to make this work.

However, since we are dealing with constants here: Wouldn't it be 
sufficient if you just said #.+attribute-item-type+ (so evaluate the 
form at read time, which means that the value seen by the defclass form 
is the integer constant value).

Finally, a more general Lisp style remark: The use of numbers for 
enumerations is a bit unlispy. It's more common to actually use symbols 
here. So you could as well say attribute-item-type or 
:attribute-item-type (to not worry about whether a form needs to be 
evaluated or not, since keywords always evaluate to themselves). If you 
rely on symbols instead of numbers, your problem will disappear 
completely...


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/