From: Joel Ray Holveck
Subject: Re: reflection
Date: 
Message-ID: <y7cit2idkon.fsf@sindri.juniper.net>
> What is the `hello world' of reflection in lisp
> or common lisp?  I mean `hello world' in the metaphorical
> sense of the phrase here.

Well, "reflective" is a very general term... in terms of generality,
I'd put it somewhere between "orthogonal" and "object-oriented".
There's reflection functions for the type system (such as SUBTYPEP),
the object system (such as CLASS-SLOTS), and other parts of Common
Lisp.

Here's a few examples of the above two for you to chew over, though.
Here's a function I wrote when I was toying with a program to graph
the type tree in CL:

(defun subtypes-of (type)
  "Return two values: the subtypes and supertypes of TYPE.
The only types considered are symbols."
  (loop
   for sym being the external-symbols in :common-lisp
   when (ignore-errors (subtypep sym t))
     when (subtypep sym type)
       collect sym into subtypes
     end
     and when (subtypep type sym)
       collect sym into supertypes
   finally (return (values subtypes supertypes))))

A few notes on the above code snippet.  It's recently been pointed out
to me that (SUBTYPE FOO T) is not guaranteed to do anything sensible
if FOO is not a type specifier.  For example, on CMUCL, using
type-related symbols such as SATISFIES and MOD will signal an error.
That's what the IGNORE-ERRORS is for.  It mostly seems to work on
CMUCL, but isn't guaranteed to work anywhere.

Now, here's another code snippet, this one from an implementation of
INSPECT I was playing with:

(define-inspector standard-object (item type context)
  (declare (ignore type))
  (dolist (slot (reverse (pcl:class-slots (class-of item))))
    (let ((slot-name (pcl:slot-definition-name slot)))
      (cond
	((slot-boundp item slot-name)
	 (genspect-slot context slot-name (pcl:slot-value item slot-name)
			(pcl:slot-definition-type slot)))
	(t
	 (genspect-unbound-slot context slot-name
				(pcl:slot-definition-type slot)))))))

The PCL package is where MOP operations are in CMUCL.

Cheers,
joelh

From: Rahul Jain
Subject: Re: reflection
Date: 
Message-ID: <87sn1lq5hv.fsf@localhost.localdomain>
Joel Ray Holveck <·····@juniper.net> writes:

> Now, here's another code snippet, this one from an implementation of
> INSPECT I was playing with:
> 
> (define-inspector standard-object (item type context)
>   (declare (ignore type))
>   (dolist (slot (reverse (pcl:class-slots (class-of item))))
>     (let ((slot-name (pcl:slot-definition-name slot)))
>       (cond
> 	((slot-boundp item slot-name)
> 	 (genspect-slot context slot-name (pcl:slot-value item slot-name)
> 			(pcl:slot-definition-type slot)))
> 	(t
> 	 (genspect-unbound-slot context slot-name
> 				(pcl:slot-definition-type slot)))))))

Does this mean that CMUCL will finally be able to inspect CLOS
instances some time in the near future?

Note that I don't think cl:class-of will work with MOP functions. You
need to use pcl:class-of to get a proper metaclass for most/all of
them to work with. If this example does work, please disregard my
random blathering. :)

It would also be nice to be able to traverse the class of an instance
in the inspector, if you feel like adding that functionality.

Other forms of reflection the OP might wish to consider:

setf places - get-setf-expansion, define-setf-expander, defsetf,
              define-modify-macro
runtime error-handling - handler-case, restart-case, compute-restarts,
                         invoke-restart
array-element specialization - upgraded-array-element-type
compiler-macros - define-compiler-macro, compiler-macro-function

Some useful techniques for effectively using reflection are the
EVAL-WHEN special form and the #. reader-macro.

To get full details on how these features work, please consult the
hyperspec at www.xanalys.com or apt-get install hyperspec on debian.

-- 
-> -/                        - Rahul Jain -                        \- <-
-> -\  http://linux.rice.edu/~rahul -=-  ············@techie.com   /- <-
-> -X "Structure is nothing if it is all you got. Skeletons spook  X- <-
-> -/  people if [they] try to walk around on their own. I really  \- <-
-> -\  wonder why XML does not." -- Erik Naggum, comp.lang.lisp    /- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   (c)1996-2002, All rights reserved. Disclaimer available upon request.
From: Joel Ray Holveck
Subject: Re: reflection
Date: 
Message-ID: <y7celd5evk4.fsf@sindri.juniper.net>
> Does this mean that CMUCL will finally be able to inspect CLOS
> instances some time in the near future?

I was not modifying the CMUCL code... this is my own work, independent
of CMUCL.  But you can replace CMUCL's INSPECT with my library if you
like.

> Note that I don't think cl:class-of will work with MOP functions. You
> need to use pcl:class-of to get a proper metaclass for most/all of
> them to work with. If this example does work, please disregard my
> random blathering. :)

It does work, surprisingly enough.  I had the same thought, but it
seems to do fine.

> It would also be nice to be able to traverse the class of an instance
> in the inspector, if you feel like adding that functionality.

Sounds like a good idea, thanks!

I'll go ahead and discuss what this program is.  It's a generalized
inspector, one in which the front-ends and back-ends are separated
out.  The basic idea is that you can supply front-ends that need to
implement a few particular methods, probably in just a few lines.
I've written front-ends for a TTY (58 lines) and for web access via
PortableAserve (181 lines), and a GTK front-end probably wouldn't be
hard.

The back-ends are the inspectors for particular types.  What you saw
was one example, for STANDARD-OBJECT.  There are also inspectors for
T, SEQUENCE, SYMBOL, and HASH-TABLE.  Since the back-ends can be
defined separately, you can write your own application-specific ones
using a few defined functions.  For reference, these take up 64 lines
total.  (This is similar to how you would define a PRINT-OBJECT
method.)

I'll add that even though I'm posting this from my work email address,
this library is my own.  Don't blame Juniper for any shortcomings.

Speaking of shortcomings: it works okay, but there's many areas for
improvement.  Proper use of method combination could simplify the
front-end interface significantly and make the code's organization
cleaner.  The distinction between an object's actual type and its
intended type (ie, do we present NIL as a symbol or a list) is not
very well done; I could learn a few things from CLIM here.  I've tried
to account for this in the back-end interface, though.  I thought I'd
clean the rest of this up when I got around to it, but it's been
several months and I may never get around to it.  Naturally, the
normal cross-compatibility issues when dealing with MOPs may apply.

So, if anybody is interested after hearing the above caveats, I'll
distribute it.

Cheers,
joelh
From: Thomas F. Burdick
Subject: Re: reflection
Date: 
Message-ID: <xcv4re11eyc.fsf@conquest.OCF.Berkeley.EDU>
Joel Ray Holveck <·····@juniper.net> writes:

> The PCL package is where MOP operations are in CMUCL.

Well, there is a MOP package, but unfortunately the whole MOP isn't in
there.  I keep meaning to submit a patch for this...

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'