From: Gregory D. Jorstad
Subject: Re: Observer implementation in CLOS
Date: 
Message-ID: <34DF1338.1DD0@cs.umass.edu>
Tim Bradshaw wrote:
> 
> * Gregory D Jorstad wrote:
> > I am interested in code or ideas in implementing a "trace" capability
> > which would allow you to add hooks to an accessor access in a CLOS
> > object to call arbitrary code or another object when the value is
> > changed.
> 
> > I was wondering if anyone had already implemented something like this.
> > I imagine is actually isn't too hard since you can probably mixin a
> > class which would define :after methods on setfs for accessors or create
> > special defclass that would define those methods.
> 
> I'm not sure why this is non-trivial, although I may be missing
> something.  If I want to do this I just define before / after / around
> methods on accessors by hand when I need to. Do you want something
> more automatic or different than that?  Can you explain what if so?
> 
> --tim

Mostly I was wondering if someone had defined anything full-featured for
this already, i.e. something more generic than defining your own
accessors
on each one.

First of all the capability to add traces should be dynamic, i.e. you
should
be able to add and remove traces during the course of a program's
execution.
You should also be able to add multiple traces to one thing.  This rules
out
doing an :after method for each trace you want to add as you would need
a
mixin for each trace then, and you don't want to predefine the number of
traces
you can have.

That means that you probably should have a mixin traceable class which
you add to 
any classes you want to allow traces on.  You would want to create after
methods on all of the accessors specialized on this traceable class.  In
these
accessors you would access some variables (from the traceable class)
that store 
which traces exist.  That would allow you to call all the trace
procedures when an
accessor is accessed.  This probably calls for a special defclass form
which creates
these accessors for you automatically, either defining them for all
accessors or
accessors that specify individually with some :trace indicator.

Other administrative details are keeping returning a handle to the trace
so you
can untrace it.  An important architecture decision is whether you want
to allow traces to defined on individual objects, classes, or both.  An
important implementation detail is whether or not you want to store a
list of the
traces for each accessor or store a single list of all traces in the
"traceable
class".  The first solution might require defining an extra slot in a
special
defclass form for each traced accessors which stores the traces for that
accessor.
That would probably be the most efficient solution.

-Greg