From: Eric Lavigne
Subject: accessing unspecified slots
Date: 
Message-ID: <1137825491.342264.325090@o13g2000cwo.googlegroups.com>
(defstruct ball
     color
     radius
     owner)

(defvar a-ball (make-ball :color "red" :radius 5 :owner "Paul"))

(list-slots-symbol 'ball) --> (color radius owner)
(list-slots-instance a-ball) --> (color radius owner)

This is a trivial example to illustrate my question. Does Common Lisp
have a way to inspect the slots of a class (struct is type of class)?
In other words, how would I go about implementing either of the
"list-slots" procedures above?

If I know that ball has a slot called color, it's easy to ask what
color a certain ball is. The issue here, though, is how to avoid saying
the word "color", to write a procedure that can figure out on its own
which slots exist.

The closest I have found is "describe", but this function is designed
to produce human-readable output in an implementation dependent manner.
What I am looking for is a way to write procedures that can act on
classes that they weren't specifically designed for.

This train of thought started with an idea from Ruby on Rails, in which
the default "view" of a class is a table whose columns show the slot
names and slot values. Despite the origin of the thought, though, it is
now mostly an issue of curiosity. This seems like the sort of thing
that Common Lisp could do, but I don't have any idea how to approach
the problem.

From: M Jared Finder
Subject: Re: accessing unspecified slots
Date: 
Message-ID: <43D1E403.2040405@hpalace.com>
Eric Lavigne wrote:
> (defstruct ball
>      color
>      radius
>      owner)
> 
> (defvar a-ball (make-ball :color "red" :radius 5 :owner "Paul"))
> 
> (list-slots-symbol 'ball) --> (color radius owner)
> (list-slots-instance a-ball) --> (color radius owner)

 From the CLOS faq:

Subject: [5-5] Given the name of a class, how can I get the names
                of its slots?

(defun class-slot-names (class-name)
   "Given a CLASS-NAME, returns a list of the slots in the class."
   (mapcar #'clos:slot-definition-name
           (clos:class-slots (find-class class-name))))

(defmethod class-slot-names ((instance standard-object))
   "Given an INSTANCE, returns a list of the slots in the instance's class."
   (mapcar #'clos:slot-definition-name
           (clos:class-slots (class-of instance))))

You can use CLASS-DIRECT-SLOTS instead of CLASS-SLOTS if you don't
want inherited slots. Note that these functions are from the
meta-object protocol specified in the original X3J13 draft spec
(document X3J13/88-003), and may not be supported by all Lisps.

   -- MJF
From: Eric Lavigne
Subject: Re: accessing unspecified slots
Date: 
Message-ID: <1137836028.248161.141270@z14g2000cwz.googlegroups.com>
> From the CLOS faq:
> Subject: [5-5] Given the name of a class, how can I get the names
>                of its slots?

Thanks for the pointer. Now I'm off to learn all about CLOS. That's one
of the areas of CL that I have mostly ignored so far, and I should have
known it would relate to a question like this.
From: Geoffrey Summerhayes
Subject: Re: accessing unspecified slots
Date: 
Message-ID: <ZtlAf.20711$924.279897@news20.bellglobal.com>
"Eric Lavigne" <············@gmail.com> wrote in message ·····························@o13g2000cwo.googlegroups.com...
> (defstruct ball
>     color
>     radius
>     owner)
>
> (defvar a-ball (make-ball :color "red" :radius 5 :owner "Paul"))
>
> (list-slots-symbol 'ball) --> (color radius owner)
> (list-slots-instance a-ball) --> (color radius owner)
>

MOP supports it. But each implementation varies on what
package SLOT-DEFINITION-NAME and CLASS-SLOTS is in.
But essentially it's this

(defun list-slots(class)
  (mapcar #'slot-definition-name
          (class-slots (find-class class))))

For a more complete definition, try googling the NG.

---
Geoff
 
From: Kenny Tilton
Subject: Re: accessing unspecified slots
Date: 
Message-ID: <YOmAf.5887$SD.4120@news-wrt-01.rdc-nyc.rr.com>
Eric Lavigne wrote:
> (defstruct ball
>      color
>      radius
>      owner)
> 
> (defvar a-ball (make-ball :color "red" :radius 5 :owner "Paul"))
> 
> (list-slots-symbol 'ball) --> (color radius owner)
> (list-slots-instance a-ball) --> (color radius owner)
> 
> This is a trivial example to illustrate my question. Does Common Lisp
> have a way to inspect the slots of a class (struct is type of class)?
> In other words, how would I go about implementing either of the
> "list-slots" procedures above?
> 
> If I know that ball has a slot called color, it's easy to ask what
> color a certain ball is. The issue here, though, is how to avoid saying
> the word "color", to write a procedure that can figure out on its own
> which slots exist.
> 
> The closest I have found is "describe", but this function is designed
> to produce human-readable output in an implementation dependent manner.
> What I am looking for is a way to write procedures that can act on
> classes that they weren't specifically designed for.
> 
> This train of thought started with an idea from Ruby on Rails, in which
> the default "view" of a class is a table whose columns show the slot
> names and slot values. Despite the origin of the thought, though, it is
> now mostly an issue of curiosity. This seems like the sort of thing
> that Common Lisp could do, but I don't have any idea how to approach
> the problem.
> 

1. If you do not care about portability, use an implementation that will 
tell you the slots of a defstruct.

2. Use CLOS. It is fast enough vs defstruct for any Web app

3. Write your own MY-DEFSTRUCT macro that expands into a CL defstruct as 
well as sticking the slot names in a property on the symbolic name of 
the defstruct.

kenny
From: Rainer Joswig
Subject: Re: accessing unspecified slots
Date: 
Message-ID: <joswig-181E06.15155021012006@news-europe.giganews.com>
In article <························@o13g2000cwo.googlegroups.com>,
 "Eric Lavigne" <············@gmail.com> wrote:

> (defstruct ball
>      color
>      radius
>      owner)
> 
> (defvar a-ball (make-ball :color "red" :radius 5 :owner "Paul"))
> 
> (list-slots-symbol 'ball) --> (color radius owner)
> (list-slots-instance a-ball) --> (color radius owner)
> 
> This is a trivial example to illustrate my question. Does Common Lisp
> have a way to inspect the slots of a class (struct is type of class)?

CL-USER 1 > (defstruct foo)
FOO

CL-USER 2 > (class-of (find-class 'foo))
#<STANDARD-CLASS STRUCTURE-CLASS 1014AA43>

CL-USER 3 > (defclass bar () ())
#<STANDARD-CLASS BAR 1008A227>

CL-USER 4 > (class-of (find-class 'bar))
#<STANDARD-CLASS STANDARD-CLASS 1014AAAF>

So, a structure is a STRUCTURE-CLASS and a CLOS class is (usually)
a STANDARD-CLASS. They are very different. It also means that (many/most/...)
operations defined on CLOS classes are not supported for structures.

Structures are a historic relict from a time when there was
no CLOS. Sometimes people use structures because some
operations may be more efficient for structures than for
classes. Several Lisp implementations have added non-standard
features to their CLOS implementations to make some of these
operations as fast as the operations on structures.

Until you have special needs that makes the use of structures
necessary, I would just forget that there are structures
and use CLOS classes (via DEFCLASS
and the like).


> In other words, how would I go about implementing either of the
> "list-slots" procedures above?
> 
> If I know that ball has a slot called color, it's easy to ask what
> color a certain ball is. The issue here, though, is how to avoid saying
> the word "color", to write a procedure that can figure out on its own
> which slots exist.
> 
> The closest I have found is "describe", but this function is designed
> to produce human-readable output in an implementation dependent manner.
> What I am looking for is a way to write procedures that can act on
> classes that they weren't specifically designed for.
> 
> This train of thought started with an idea from Ruby on Rails, in which
> the default "view" of a class is a table whose columns show the slot
> names and slot values. Despite the origin of the thought, though, it is
> now mostly an issue of curiosity. This seems like the sort of thing
> that Common Lisp could do, but I don't have any idea how to approach
> the problem.

Look for functions like CLASS-SLOTS and CLASS-DIRECT-SLOTS.
Probably in a package CLOS.

CL-USER 6 > (apropos "CLASS-SLOTS")
...
CLASS-SLOTS (defined)
...

CL-USER 12 > (defclass bar () (a b c))
#<STANDARD-CLASS BAR 10B8B93F>

CL-USER 13 > (class-slots (find-class 'bar))
(#<STANDARD-EFFECTIVE-SLOT-DEFINITION A 1007C47F> #<STANDARD-EFFECTIVE-SLOT-DEFINITION B 1007C22F> #<STANDARD-EFFECTIVE-SLOT-DEFINITION C 1007BFDF>)

-- 
http://lispm.dyndns.org/