From: John Flynn
Subject: Basic CLOS design questions
Date: 
Message-ID: <r_JK6.4180$ZJ.156213@ozemail.com.au>
Hi all. As I mentioned the other day, I'm new to CLOS. I'm having some fun
experimenting, trying to get a handle on some fairly basic OO techniques.

This is a design question as much as it is a Lisp question: I'm interested
in how I can best handle this kind of simple scenario in Common Lisp:

Suppose I have an object that wants to notify other (unknown) objects of
significant events that happen to it (or events that it generates).

Eg. I have a time bomb. It has two methods: "tick" and "explode". Whenever
it ticks or explodes, I want it to broadcast a message to any interested
observers. The bomb doesn't know or care who the interested observers might
be, so I'd like a mechanism for allowing other objects to hook up event
handlers to the bomb's "tick" and "explode" methods at runtime. Any
interested parties can register their interest in the bomb by hooking up an
event handler, which is then called automatically when the bomb ticks or
explodes.

Suppose we have three interested parties: a policeman, an explosives expert
and a barber. They're all going to react differently to the tick event.

The way I'm doing this currently is:

Define a "person" class and derive "policeman", "explosives-expert" and
"barber" from person.

Define a "time-bomb" class and some "do-something" methods by which
policeman, barber and explosives-expert each respond to the bomb's ticking.

In order to handle the dispatching of messages from the bomb to the
bystanders, I'm deriving "time-bomb" from a base class called "observable".
Observable contains a hashtable that maps an event name to a list of
messages. These messages are structures containing a recipient and an
appropriate method to call in response to an event.

The "observable" class has a couple of associated methods:

"observe-event" is a means by which a derived class can register a list of
event-names that can have event handlers hooked up to them. (It just makes
empty entries in the hashtable, so that other entities can later add an
event handler).

"add-event-handler" takes an observable object, an event name, an observer
and an appropriate method to call when the event occurs. It adds an entry to
the observed object's hash table (event-map).

(If this explanation isn't clear enough, I'll post some code).

Although my solution works fine for this example, I'm a little unsure of
myself here.
Any suggestions on how this ought to be done? Eg. is there a commonly used
technique that is very general and very widely applicable?

Please bear in mind that, as well as not knowing much of CL, I'm also quite
unfamiliar with "design patterns" at this stage, so my understanding of the
terminology and the concepts (not to mention performance issues) is likely
to be quite naive.

Thanks in advance for any hints and suggestions.

From: Steven M. Haflich
Subject: Re: Basic CLOS design questions
Date: 
Message-ID: <3AFB79C3.240A74B9@pacbell.net>
This is knowingly not directly responsive to your question, but
first things first:

John Flynn wrote:

> Eg. I have a time bomb. It has two methods: "tick" and "explode".

In Common Lisp objects (or classes or whatever) don't have methods.
Generic functions have methods.  While we Lisp programmers might casually
attribute a method with only a single discriminating argument as somehow
belonging to that discriminated class, this is really a C++/Java barbarism.
Narrowing your design thinking to those terms might restrict your design
to unnatural solutions.

> In order to handle the dispatching of messages from the bomb to the
> bystanders, I'm deriving "time-bomb" from a base class called "observable".

I wonder that you mean by "deriving" here.  In a multiple-inheritance
object language like CL one would generally speak of an observable "mixin".
This way of composing orthogonal classes allows orthogonal functionality
to be kept separate.  Java has other ways of doing this kind of composing --
but often this results in turgid, unnatural chains of class inheritance,
or else volumous repetitive code deligate entire interfaces to some handler
class.  Multiple inheritance is (IMO) often terser for these kinds of
problems. and therefore yields clearer code.

Basically, I'm sugesting when in the Common Lisp world you should try to
think in terms of multiple inheritance, and solutions may be more natural
to CL.  I can't tell from your message whether you already think this way,
but terms like "derived from" make me suspicious.
From: John Flynn
Subject: Re: Basic CLOS design questions
Date: 
Message-ID: <f9MK6.4241$ZJ.157494@ozemail.com.au>
"Steven M. Haflich" <·······@pacbell.net> wrote in message
······················@pacbell.net...
[...]
> In Common Lisp objects (or classes or whatever)
> don't have methods. Generic functions have methods.
> While we Lisp programmers might casually
> attribute a method with only a single
> discriminating argument as somehow belonging
> to that discriminated class, this is really a
> C++/Java barbarism.

Yes, I know what you mean. I'm getting used to the idea that methods don't
belong to classes but are, as you say, called according to their
discriminating arguments. (In my program I'm using methods that take both a
'bomb' and derivatives of 'person' as discriminating arguments, so I do
understand the basic concept. (Still using the 'old' terminology though ...)

> Narrowing your design thinking to those terms might
> restrict your design to unnatural solutions.

This is what I'm most looking forward to in CLOS. I've used languages that
have multiple
inheritance (C++, Eiffel, Python - though I'm no expert in any of them).
CLOS is the first system I've used that has generic functions.

My main problem is that I haven't seen any examples of real-world CLOS
applications yet, and I don't have access to any books that contain sizeable
examples - so it's going to take some time for me to adjust to new
possibilities.

(Which is essentially why I'm doing this).

> I wonder that you mean by "deriving" here [...]

Simply "inherits from". In my toy example, there's only one superclass, so I
guess "base class" or
"mixin" would be equally appropriate.

> Basically, I'm sugesting when in the Common Lisp
> world you should try to think in terms of
> multiple inheritance, and solutions may be
> more natural to CL.  I can't tell from your
> message whether you already think this way,
> but terms like "derived from" make me suspicious.

Yep, point taken. I don't think I have too many serious prejudices to forget
about. OTOH, the
prejudices I _do_ have are likely to be quite serious ones until I've had
more exposure to the alternatives.

I'm enjoying Lisp a lot so far. It's coupled with disappointment that I
wasn't aware of it yesterday. If
I was, I feel I'd (potentially) be a much better programmer than I am today.

You mentioned Java. No, fortunately that's not something I have to overcome.
I've even _tried_ to
like Java a few times, but it always felt bland and featureless to me. I'm
now quite glad I never took to it in a serious way.
From: Friedrich Dominicus
Subject: Re: Basic CLOS design questions
Date: 
Message-ID: <87ae4kp7js.fsf@frown.here>
"John Flynn" <··········@yahoo.com.au> writes:

> 
> My main problem is that I haven't seen any examples of real-world CLOS
> applications yet, and I don't have access to any books that contain sizeable
> examples - so it's going to take some time for me to adjust to new
> possibilities.

I think CL-HTTP is very real. So you might look at it...

What might help too is looking into a good Common Lisp book.

Regards
Friedrich
From: Pierre R. Mai
Subject: Re: Basic CLOS design questions
Date: 
Message-ID: <87itj8rurg.fsf@orion.bln.pmsf.de>
"John Flynn" <··········@yahoo.com.au> writes:

> My main problem is that I haven't seen any examples of real-world CLOS
> applications yet, and I don't have access to any books that contain sizeable
> examples - so it's going to take some time for me to adjust to new
> possibilities.

You might want to get both of the following books, the first of which
gives a very thorough introduction to CLOS (including some non-trivial
usage techniques), and the second describes the Metaobject Protocol,
which is a layered de-facto standard for a reflective substrate upon
which CLOS is built, which is itself implemented in CLOS, and hence
contains many non-trivial real-world implementation techniques:

* Keene, Sonya E.: Object Oriented Programming in Common Lisp
  - A Programmers Guide to the Common Lisp Object System
  http://www.amazon.com/exec/obidos/ASIN/0201175894/
  http://www.amazon.de/exec/obidos/ASIN/0201175894/

* Kiczales, Gregor et al: The Art of the Metaobject Protocol
  http://www.amazon.com/exec/obidos/ASIN/0262610744/
  http://www.amazon.de/exec/obidos/ASIN/0262610744/

[Note that the links to Amazon.com are purely for reference purposes,
 and are neither an endorsement of Amazon.com, nor are they part of
 any partner-program, hence I don't profit from books purchased
 through them.]

You can get the source code to PCL, which is a CLOS/MOP implementation
done by Kiczales, et al at Xerox PARC, which should give you some more
interesting insights.  A currently maintained version of PCL is
included in the CMU CL source code in the src/pcl subdirectory.  See
http://www.cons.org/cmucl/ for details on CMU CL.

Note that the thing that in my experience is the hardest for CLOS
newcomers from other OO languages to grasp is the fact that Common
Lisp often offers more apropriate mechanisms for certain constructs
which don't even involve CLOS, e.g. where other languages have to
kludge around with messages, event-handlers, etc., a list of closures
(often called a hook in Lisp) will be a much better solution.

I haven't looked at your original problem in depth, but it seems to me
the only thing you want is to have the bomb inform registered parties
of certain events.  The easiest way to do this is to have the bomb
include a hook for each event, e.g.:

(defclass bomb ()
  ((tick-hook :initform nil :accessor bomb-tick-hook)
   (explode-hook :initform nil :accessor bomb-explode-hook)))

(defmethod bomb-add-to-tick-hook ((bomb bomb) function)
  (push function (bomb-tick-hook bomb))
  t)

(defmethod bomb-add-to-explode-hook ((bomb bomb) function)
  (push function (bomb-tick-hook bomb))
  t)

(defmethod bomb-tick ((bomb bomb))
  ;; Do whatever makes the bomb tick here...
  t)

(defmethod bomb-tick :after ((bomb bomb))
  ;; This is in an after method, but could be folded into the main
  ;; method, depending on circumstances and design constraints.
  ;; If we do it this way, then descendants of bomb can override
  ;; the ticking behaviour, without having to worry about the
  ;; hook handling stuff.
  (dolist (function (bomb-tick-hook bomb))
    (funcall function bomb)))

;; Ditto for bomb-explode...

If you design the information mechanisms this way, you have freed bomb
from needing to know anything at all about the parties it informs,
i.e. what classes they inherit from, what generic functions are
defined for them, what kind of information should be passed to them in
addition to the bomb that ticked/exploded, etc.  This makes for very
low cohesion, and hence few problems if the design of the other
parties have to change.

If you need to allow the removal of functions from the hook, then you
might want to use something other than the function as a key, but
that's another issue.

Of course you can do other stuff as well, i.e. an bomb-observer-mixin,
and generic functions of the form

(defgeneric inform-bomb-observer-of-bomb-tick (observer bomb))
(defgeneric inform-bomb-observer-of-bomb-explosion (observer bomb))
(defgeneric add-bomb-observer-to-bomb (observer bomb))
(defgeneric remove-bomb-observer-from-bomb (observer bomb))

Where an after-method on bomb-tick/bomb-explode calls the correct
inform GFs.

Which design is more apropriate really depends on a lot of things,
e.g. things like "Are observers generally interested in both events,
or are there lots of them that only care about one but not the other?".

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: John Flynn
Subject: Re: Basic CLOS design questions
Date: 
Message-ID: <O%TK6.4426$ZJ.166583@ozemail.com.au>
"Pierre R. Mai" <····@acm.org> wrote in message
···················@orion.bln.pmsf.de...

[Book suggestions, PCL source, etc.]

> I haven't looked at your original problem in depth, but it seems to me
> the only thing you want is to have the bomb inform registered parties
> of certain events.

Yes. I chose the bomb problem as an example of a general idea. At the back
of my mind, I was thinking about how I might at some stage contribute to
Common Lisp bindings for a portable GUI toolkit. The idea of firing events
notifications to unknown parties is pretty important in this context, so I
wanted to get a basic idea of how it's done in Lisp. (I quite like the way
Qt does it in C++ www.trolltech.com , but I haven't seen a wide range of
alternatives to compare it with).

> The easiest way to do this is to have the bomb
> include a hook for each event, e.g.: [...]

That's pretty much the approach I'm taking, except that 'bomb' itself
doesn't contain any hooks; the 'observable' mixin tries to take care of
that. ('Bomb' inherits the notification mechanism). This approach works OK
for my toy example, but I don't know whether it's good for much else.

[...]

> If you design the information mechanisms this way, you have freed bomb
> from needing to know anything at all about the parties it informs,
> i.e. what classes they inherit from, what generic functions are
> defined for them [...]

Yes. That's exactly what I'm after.

> If you need to allow the removal of functions from the hook, then you
> might want to use something other than the function as a key, but
> that's another issue.

OK - but I'm curious: why would removing a function be a problem?

Thanks for the book suggestions, etc.
From: Kent M Pitman
Subject: public paranoia about internet [was: Re: Basic CLOS design questions]
Date: 
Message-ID: <sfw1ypvc0lb.fsf_-_@world.std.com>
Btw, as an aside, unless you want to find yourself badly misquoted in
a newspaper one day for the chosen of your program, I'd pick a
different example domain to play with.  Alas...

Competent media would figure this out, but I wouldn't rely on
competence in the media to protect me.  To us, a toy program for
teaching purposes is one thing.  We know you don't have hardware
tendrils on what you're building and that the domain chosen is arbitrary.
But people who don't understand just look at the words they do understand
and try to guess what the rest must be about.  And to someone who doesn't know
better, and who just strings the word "toy" and "program" and other
things together into strings until it makes sentences that sound good
in the lead paragraph of a story, there's a lot of potential for 
misinterpretation, whether accidental or otherwise.

With the help of things like www.deja.com, usenet discussion lasts
forever, and the most oddball thing you've ever said will probably be
on a potential employer's screen when you interview for your next
job... or some job in the future, anyway.

Probably too late, though.  I hear the government has little programs
that are continually tracking all transactions on the internet looking
for key phrases, etc., so they probably already have a file open on
you.  And on the various ones of us who offered you programming tips,
too, I suppose.  Sigh...

I wonder what language such government tracking programs are written
in.  Hmm.
From: Geoff Summerhayes
Subject: Re: public paranoia about internet [was: Re: Basic CLOS design questions]
Date: 
Message-ID: <tfo7dodcraaab@corp.supernews.com>
"Kent M Pitman" <······@world.std.com>
who we fail to recall writing a message ·······················@world.std.com that said...

> Btw, as an aside, unless you want to find yourself badly misquoted in
> a newspaper one day for the chosen of your program, I'd pick a
> different example domain to play with.  Alas...
>
> Competent media would figure this out, but I wouldn't rely on
> competence in the media to protect me.  To us, a toy program for
> teaching purposes is one thing.  We know you don't have hardware
> tendrils on what you're building and that the domain chosen is arbitrary.
> But people who don't understand just look at the words they do understand
> and try to guess what the rest must be about.  And to someone who doesn't know
> better, and who just strings the word "toy" and "program" and other
> things together into strings until it makes sentences that sound good
> in the lead paragraph of a story, there's a lot of potential for
> misinterpretation, whether accidental or otherwise.
>
> With the help of things like www.deja.com, usenet discussion lasts
> forever, and the most oddball thing you've ever said will probably be
> on a potential employer's screen when you interview for your next
> job... or some job in the future, anyway.
>
> Probably too late, though.  I hear the government has little programs
> that are continually tracking all transactions on the internet looking
> for key phrases, etc., so they probably already have a file open on
> you.  And on the various ones of us who offered you programming tips,
> too, I suppose.  Sigh...
>
> I wonder what language such government tracking programs are written
> in.  Hmm.

And how would they handle the spambot-generated cruft, those numbers
*could* be a sophisticated code hiding in plain view. Of course, the
sheer weight of all that (lack of) information might just make their
system...wait for it...bomb! ;-)

Geoff
From: eric dahlman
Subject: Re: public paranoia about internet [was: Re: Basic CLOS design questions]
Date: 
Message-ID: <tz4u22ryemz.fsf@sibelius.cs.colostate.edu>
"Geoff Summerhayes" <·············@hNoOtSmPaAiMl.com> writes:

> "Kent M Pitman" <······@world.std.com>
> who we fail to recall writing a message ·······················@world.std.com that said...
> 
  [snip]      
> > Probably too late, though.  I hear the government has little programs
> > that are continually tracking all transactions on the internet looking
> > for key phrases, etc., so they probably already have a file open on
> > you.  And on the various ones of us who offered you programming tips,
> > too, I suppose.  Sigh...
> >
> > I wonder what language such government tracking programs are written
> > in.  Hmm.
> 
> And how would they handle the spambot-generated cruft, those numbers
> *could* be a sophisticated code hiding in plain view. Of course, the
> sheer weight of all that (lack of) information might just make their
> system...wait for it...bomb! ;-)

Isn't this what M-x spook is for ;-) Althought I am more partial to
M-x insert-zippyism myself.

ObYow!: ..  Once upon a time, four AMPHIBIOUS HOG CALLERS attacked a
 family of DEFENSELESS, SENSITIVE COIN COLLECTORS and brought DOWN
 their PROPERTY VALUES!!

-Eric
From: Janis Dzerins
Subject: Re: public paranoia about internet [was: Re: Basic CLOS design questions]
Date: 
Message-ID: <87zocj6bfj.fsf@asaka.latnet.lv>
Kent M Pitman <······@world.std.com> writes:

> Probably too late, though.  I hear the government has little programs
> that are continually tracking all transactions on the internet looking
> for key phrases, etc., so they probably already have a file open on
> you.  And on the various ones of us who offered you programming tips,
> too, I suppose.  Sigh...
> 
> I wonder what language such government tracking programs are written
> in.  Hmm.

And emacs has a litlle function that helps make these little programs
a little more busy. The function is called 'spook' and sample output
is:

Ortega Cocaine Waco, Texas explosion Nazi genetic PLO bomb radar Uzi
Semtex cracking World Trade Center Serbian Kennedy

or this:

Khaddafi Serbian SDI World Trade Center FBI cracking Uzi plutonium
$400 million in gold bullion nuclear DES Semtex Kennedy spy Albanian

-- 
Janis Dzerins

  If million people say a stupid thing it's still a stupid thing.
From: John Flynn
Subject: Re: public paranoia about internet [was: Re: Basic CLOS design questions]
Date: 
Message-ID: <WVVK6.4467$ZJ.167214@ozemail.com.au>
"Janis Dzerins" <·····@latnet.lv> wrote in message
···················@asaka.latnet.lv...
> And emacs has a litlle function that helps make these little programs
> a little more busy.

We now have evidence that you're willing and able to control 'W' and kill
whole regions.

(Groan).
From: John Flynn
Subject: Re: public paranoia about internet [was: Re: Basic CLOS design questions]
Date: 
Message-ID: <SlVK6.4460$ZJ.167157@ozemail.com.au>
"K**t M P*tm*n" wrote:

> [...]  I hear the government has little programs
> that are continually tracking all transactions on the internet looking
> for key phrases, etc., so they probably already have a file open on
> you.  And on the various ones of us who offered you programming tips,
> too, I suppose.  Sigh...

Hmmm ... wasn't expecting such a sinister twist to my 'observer' pattern.
;-)

I hope the fact that I'm in Australia allows me to write about CLOS with
impunity? Well ... maybe not.

We have a scandal raging here at the moment. A Sydney schoolboy's personal
diary was somehow turned over to school authorities, thence to the NSW
Education Minister, who revealed some of its contents (selectively) before
parliament (and indirectly to the public). This kid had allegedly been
planning a m*ss*cre of his schoolmates and teachers; a plan which education
minister John Aquilina had heroically foiled by exposing the fiend to public
scrutiny.

It turns out the information made public was largely false. The kid's lawyer
is threatening to make the contents of the diary public unless the minister
personally apologises - so apparently the real story would be more damaging
to the minister than to the kid.

So who knows? Maybe I _will_ find myself on the front page of tomorrow's
Sydney Morning Herald.

Stranger things have happened...
From: Jens Kilian
Subject: Re: public paranoia about internet [was: Re: Basic CLOS design questions]
Date: 
Message-ID: <sfeltsqq73.fsf@bstde026.germany.agilent.com>
Kent M Pitman <······@world.std.com> writes:
> Probably too late, though.  I hear the government has little programs
> that are continually tracking all transactions on the internet looking
> for key phrases, etc., so they probably already have a file open on
> you.  And on the various ones of us who offered you programming tips,
> too, I suppose.  Sigh...
> 
> I wonder what language such government tracking programs are written
> in.  Hmm.

Highly secret code recently unearthed by North Elbonian hackers:

   10 REM KEYWORD FINDER (C) 1998 NATIOANL SECURITY AGENCY
   20 REM
   30 REM KEYWORDS TO LOOK FOR
   40 DATA "BOMB", "COCAINE", "PGP", "WAREZ", "LEWINSKY"
   ...



(Honestly, I haven't written a line of BASIC since around 1985 ;-)
-- 
··········@acm.org                 phone:+49-7031-464-7698 (TELNET 778-7698)
  http://www.bawue.de/~jjk/          fax:+49-7031-464-7351
PGP:       06 04 1C 35 7B DC 1F 26 As the air to a bird, or the sea to a fish,
0x555DA8B5 BB A2 F0 66 77 75 E1 08 so is contempt to the contemptible. [Blake]
From: Paolo Amoroso
Subject: Re: Basic CLOS design questions
Date: 
Message-ID: <NbH7Ol7D87eF=Exq0fCQgSFKBpNk@4ax.com>
On Fri, 11 May 2001 17:19:56 +1000, "John Flynn" <··········@yahoo.com.au>
wrote:

> My main problem is that I haven't seen any examples of real-world CLOS
> applications yet, and I don't have access to any books that contain sizeable
> examples - so it's going to take some time for me to adjust to new

This is a wonderful book:

  "Object-Oriented Programming in Common Lisp -
  A Programmer's Guide to CLOS"
  Sonya E. Keene
  Addison-Wesley, 1989


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/
From: Kent M Pitman
Subject: Re: Basic CLOS design questions
Date: 
Message-ID: <sfwpudgnrzm.fsf@world.std.com>
"John Flynn" <··········@yahoo.com.au> writes:

> Hi all. As I mentioned the other day, I'm new to CLOS. I'm having some fun
> experimenting, trying to get a handle on some fairly basic OO techniques.
> 
> This is a design question as much as it is a Lisp question: I'm interested
> in how I can best handle this kind of simple scenario in Common Lisp:
> 
> Suppose I have an object that wants to notify other (unknown) objects of
> significant events that happen to it (or events that it generates).

(defclass proximity-web-mixin () 
  ((neighbors :initarg :neighbors 
	      :accessor neighbors 
	      :initform '())))

(defmethod do-event :after ((thing proximity-web-mixin) event)
  (dolist (neighbor (neighbors thing))
    (do-event neighbor event)))
 
or, depending on yuur application, simulating parallelism of propagation:

(defmethod do-event :after ((thing proximity-web-mixin) event)
  (dolist (neighbor (neighbors thing))
    ;; The MP package isn't standard in common lisp, but most 
    ;; implementations offer something like this.
    (mp:process-run-function "event propagation" '()
       #'do-event neighbor event)))

If you don't do the multiple process thing, you might still want to do
something wherein you at least keep the events sorted so that nearest 
objects run the propagation first. e.g.,

(defmethod distance-from-fn (thing)
  #'(lambda (item) (distance-between thing item)))

(defmethod add-neighbor (neighor (thing proximity-web-mixin))
  (with-slot (neighbors) thing
    (setq neighbors 
          (merge (list neighbor) neighbors #'< 
	         :key (distance-from-fn thing)))))

[If you did this, it would be wise to remove the :accessor method on the 
 class definition, or to add

 (defmethod sort-neighbors ((thing proximity-mixin))
   (with-slot (neighbors) thing
     (setf neighbors (sort neighbors #'< 
		           :key (distance-from-fn thing)))))

 (defmethod (setf neighbors) :after (new-neighbors (thing proximity-web-mixin))
   (declare (ignore new-neighbors)) ;same as neighbors at this point
   (sort-neighbors))

 (defmethod initialize-instance :after ((thing proximity-web-mixin) &key)
   (sort-neighbors))

]

but then of course there are some maintenance issues if the things move.
You could also dynamically just maintain the list unordered, using

(defmethod add-neighbor (new-neighbor (thing proximity-web-mixin))
  (pushnew new-neighbor (neighbors thing)))

and do the propagation sorted, as in:

(defmethod do-event :after ((thing proximity-web-mixin) event)
  (with-slots (neighbors) thing
    (setq neighbors (sort (neighbors thing) #'<
			  :key (distance-from-fn thing)))
    (dolist (neighbor neighbors)
      (do-event neighbor event))))

And then, of course, there's the issue of whether the effect decays.
So you might want the propagation to deal with changes in effect over
distance and/or time as it propagates the delay so that effects don't
propagate throughout the universe with no loss of energy.  e.g.,

 (defmethod do-event ((thing proximity-web-mixin) event
		      &optional (propagation-count 0))
   (unless (> propagation-count (propagation-threshold event))
     (dolist (neighbor (neighbors thing)) ;or whatever
       (do-event neighbor event (1+ propagation-count)))))

> Eg. I have a time bomb. It has two methods: "tick" and "explode". Whenever
> it ticks or explodes, I want it to broadcast a message to any interested
> observers. The bomb doesn't know or care who the interested observers might
> be, so I'd like a mechanism for allowing other objects to hook up event
> handlers to the bomb's "tick" and "explode" methods at runtime. Any
> interested parties can register their interest in the bomb by hooking up an
> event handler, which is then called automatically when the bomb ticks or
> explodes.

I suggest a general method DO-EVENT based on an EVENT object.
Events should be broken down into classes like PHYSICAL-EVENT vs
VISUAL-EVENT so that some objects can reliably ignore certain events
while complaining others are unimplemented or deferring certain events
back to the event for a default handler.

> Suppose we have three interested parties: a policeman, an explosives expert
> and a barber. They're all going to react differently to the tick event.
> 
> The way I'm doing this currently is:
> 
> Define a "person" class and derive "policeman", "explosives-expert" and
> "barber" from person.

As a design point of view, I have a bug-a-boo about people making these
be aspects of the class of an object.  Your job specialty is not a property 
of you in your DNA, it's a property of your skillset and is changeable.
Nevertheless, it is popular to code these things as if it were in your DNA,
so I'll go along with this...
 
> Define a "time-bomb" class and some "do-something" methods by which
> policeman, barber and explosives-expert each respond to the bomb's ticking.

Again, the event should be a classed object so that some can see it at the
level of abstraction of a sound, while others at a finer resolution.

 (defclass sound-event (event) ((initiator ...) ...)

 (defmethod do-event ((recipient t) (sound sound-event))
   ;; default method for all objects does nothing
 )

 (defclass ticking (sound-event) ())

 (defclass explosives-expert (thing-with-ears) ())

 (defmethod hear ((who explosives-expert) (sound ticking))
   (let ((questionable-item (initiator ticking)))
     (clear-area-near questionable-item)
     (risk-life-disarming questionable-item)))

> In order to handle the dispatching of messages from the bomb to the
> bystanders, I'm deriving "time-bomb" from a base class called "observable".
> Observable contains a hashtable that maps an event name to a list of
> messages. These messages are structures containing a recipient and an
> appropriate method to call in response to an event.

It might be you don't meant he word "structure" in the formal way that
CL defines it, but for now if I were you, I'd use only class instances
as defined by defclass and would steer clear of defstruct, which
makes what we call structures.  defstruct is quite useful, actually,
but while you're learning CLOS, it's better to stick to instances.
 
> The "observable" class has a couple of associated methods:
> 
> "observe-event" is a means by which a derived class can register a list of
> event-names that can have event handlers hooked up to them. (It just makes
> empty entries in the hashtable, so that other entities can later add an
> event handler).
> 
> "add-event-handler" takes an observable object, an event name, an observer
> and an appropriate method to call when the event occurs. It adds an entry to
> the observed object's hash table (event-map).

This isn't needed, I think.  DEFMETHOD will likely suffice unless you want
the behavior of an object to vary dynamically not according to its class.
And even then, I think it will vary according to role and you're better
to classify your roles and add/remove roles from people/objects than to
be just associating functions in the ether...

> (If this explanation isn't clear enough, I'll post some code).
 
(If this answer isn't clear enough,  you should post some code.)

> Although my solution works fine for this example, I'm a little unsure of
> myself here.
> Any suggestions on how this ought to be done? Eg. is there a commonly used
> technique that is very general and very widely applicable?

Generality tends to be the enemy of efficiency, and any truly general
solution is probably massively inefficient because of the complexity
of true generality.  Look at the slowness of ray-tracing if you want
to see how just light propagation is hard to do right.  You need to figure
out what level of granularity is ok,  what effects are or might be involved,
and what can be safely omitted in your model to come up with a good level
of generalization for your task.

My background in such modeling comes mostly from MOO language/systems,
which models objects at the crude level of fairly large objects in a
room, and stuff of the approximate nature of what I've described above
is what is used to manage even propagation there.  The same techniques
work fine in Lisp, though are expressed differently.

> Please bear in mind that, as well as not knowing much of CL, I'm also quite
> unfamiliar with "design patterns" at this stage, so my understanding of the
> terminology and the concepts (not to mention performance issues) is likely
> to be quite naive.

You're doing fine.

> Thanks in advance for any hints and suggestions.

You're welcome.  Hope the above helps.

It should go without saying that I didn't actually try any of what I suggested
so there may be numerous typos or thinkos in there.  I was going pretty quick
and just sketching on the fly...
From: Shannon Spires
Subject: Re: Basic CLOS design questions
Date: 
Message-ID: <svspire-760614.10290411052001@news.sandia.gov>
In article <···············@world.std.com>, Kent M Pitman 
<······@world.std.com> wrote:

> > Suppose we have three interested parties: a policeman, an explosives 
> > expert
> > and a barber. They're all going to react differently to the tick event.
> > 
> > The way I'm doing this currently is:
> > 
> > Define a "person" class and derive "policeman", "explosives-expert" and
> > "barber" from person.
> 
> As a design point of view, I have a bug-a-boo about people making these
> be aspects of the class of an object.  Your job specialty is not a 
> property 
> of you in your DNA, it's a property of your skillset and is changeable.
> Nevertheless, it is popular to code these things as if it were in your 
> DNA,
> so I'll go along with this...

I agree with Kent's point here in principle, especially in static O-O 
languages. But somehow doing stuff like the above seems more acceptable 
to me in CLOS than it would in, say, C++.

In CLOS, an object's class membership is as mutable as its slot
contents, which means the very _existence_ of any of its slots is just 
as mutable as its slot contents.

IMHO, this mutability together with the convenience of dynamic dispatch 
and easy multiple inheritance means that the issue of whether an 
object's properties are represented by its slots, its methods, or by its 
position in the class lattice gets much more fuzzy than in more 
traditional O-O systems. This is part of the reason I find OO design
"methods" like UML to be impoverished for CLOS implementations.

Shannon Spires
·······@remove-this.nmia.com
From: Paolo Amoroso
Subject: Re: Basic CLOS design questions
Date: 
Message-ID: <TAj8OhlfAbRTQJuQeQTW1xHRAw6H@4ax.com>
On Fri, 11 May 2001 14:51:52 +1000, "John Flynn" <··········@yahoo.com.au>
wrote:

> Suppose I have an object that wants to notify other (unknown) objects of
> significant events that happen to it (or events that it generates).

You are probably referring to the observer pattern.


> Please bear in mind that, as well as not knowing much of CL, I'm also quite
> unfamiliar with "design patterns" at this stage, so my understanding of the

Lisp can do without most of the GoF design patterns. Visit the Web site of
Peter Norvig:

  http://www.norvig.com/

and get the PowerPoint presentation "Design Patterns in Dynamic
Programming". Slides #21 and 22 deal with the observer pattern in Lisp. The
slides may be a bit terse.


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/