From: Steve Lawler
Subject: CLOS Help: custom parameter specializers for methods?
Date: 
Message-ID: <69488r$b5o$1@bigboote.WPI.EDU>
Perhaps this should be in comp.lang.clos but it seems to get next to zero
traffic so...

I'm currently trying to figure out a way to write a method in CLOS that
can specialize based on the value of a slot of one of the parameters
passed to the method.  It would be akin to an eql-specializer, something
along the lines of this:

(defclass buffer ()
  ((type :accessor buffer-type)))

(defgeneric bar (parm))
(defmethod bar ((parm (eql (buffer-type parm) 'empty-buffer))) ...)
(defmethod bar ((parm (eql (buffer-type parm) 'non-empty-buffer))) ...)
(defmethod bar ((parm (eql (buffer-type parm) 'almost-full-buffer))) ...)

The intended purpose of this is that I'd like to specialize methods
depending on the "type" or "class" of the parameter, except that this
"type/class" probably isn't something deserving of being a full-fledged
CLOS class.  (as in the example, changing the class of buffer objects as
they become more or less full just to make specialization towards methods
easier to express is inappropriate and inefficient).  Furthermore, for any
given CLOS-class, I'd like to write methods which specialize on various
aspects (determined by slot values) of that class.  In this contrived
example, I might want to write some methods that specialize on parms of
class 'buffer' but also specialize on the size of the buffer, free space
in the buffer, how quickly the buffer fills up, or... whatever.

There are a few ways that I've thought of to handle this problem:

#1) Write one method, that checks the type of the argument itself

  (defmethod bar ((parm buffer))
    (case (buffer-type arg)
      (empty-buffer (empty-buffer-bar parm))
      (non-empty-buffer (non-empty-buffer-bar parm))
      (almost-full-buffer (almost-full-buffer-bar parm))))

But it seems alot like I'm basically writing my own method dispatch
function, except based on the eql-ness of one of the slots of the parm
instead of the eql-ness of the parm itself (which standard CLOS can of
course handle).

#2) Pass the buffer object as well as its 'type' slot value

  (defgeneric bar (a b))
  (defmethod bar ((a buffer) (b (eql 'empty-buffer))) ...)
  (defmethod bar ((a buffer) (b (eql 'non-empty-buffer))) ...)

  (bar buffer-object (buffer-type buffer-object))

But that's annoying because there are quite a few methods I intend to
define and I'm lazy and don't want to type in an extra (*-type *-object)
as a parm all the time.

#3) Write a macro which allows me to define methods (call it
'my-defmethod' or something) that will specialize on the values of slots
of parms, which would expand to perhaps one of the above 2 mentioned
solutions. But, I'd like to use 'defmethod' instead of my own little macro
since it is more readily apparent that I am actually defining CLOS methods
by using defmethod.  Plus, I can probably think of different ways of
specializing that might require me writing either a rather complicated
macro, or several macros.  And finally I'm pretty much a Lisp/CLOS newbie,
though that won't stop me if I have to go to great lengths to do what I
need/want to. 

I have no problem implementing any of the 3 solutions that I thought of,
I simply would rather have the expressive power of a single (defmethod...)
statement.

Any thoughts, suggestions...

Thanks
--steve

From: Barry Margolin
Subject: Re: CLOS Help: custom parameter specializers for methods?
Date: 
Message-ID: <694htg$avr@pasilla.bbnplanet.com>
In article <············@bigboote.WPI.EDU>,
Steve Lawler <········@WPI.EDU> wrote:
>Perhaps this should be in comp.lang.clos but it seems to get next to zero
>traffic so...

And how will it get more traffic if CLOS questions aren't posted there?
I think it gets little traffic because there isn't much discussion of CLOS
-- it's not like they're all discussing it here, either.

But maybe there isn't really a need for the separate group any more.

>I'm currently trying to figure out a way to write a method in CLOS that
>can specialize based on the value of a slot of one of the parameters
>passed to the method.

I can't think of a way to do this automatically (well, maybe you can do it
by defining a new class of generic function using the MOP, but I'm not as
familiar with it so I can't suggest specifics).

Perhaps you could reconsider the design that caused this requirement.  Why
are you putting this tag in a slot, rather than making empty-buffer,
non-empty-buffer, and almost-full-buffer subclasses or mixin classes?

You can do it using a wrapper method and internal methods:

(defmethod bar ((b buffer) ...)
  (bar-internal (buffer-type b) b ...))

(defmethod bar-internal ((type (eql empty-buffer)) (b buffer) ...) ...)
(defmethod bar-internal ((type (eql non-empty-buffer)) (b buffer) ...) ...)
(defmethod bar-internal ((type (eql almost-full-buffer)) (b buffer) ...) ...)

You could possibly automate some of this using macros, but it's hard to say
without understanding the application.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
Support the anti-spam movement; see <http://www.cauce.org/>
Please don't send technical questions directly to me, post them to newsgroups.
From: Steve Lawler
Subject: Re: CLOS Help: custom parameter specializers for methods?
Date: 
Message-ID: <696e3v$b49$1@bigboote.WPI.EDU>
Barry Margolin (······@bbnplanet.com) wrote:
: 
: Perhaps you could reconsider the design that caused this requirement.  Why
: are you putting this tag in a slot, rather than making empty-buffer,
: non-empty-buffer, and almost-full-buffer subclasses or mixin classes?

Well... this started from a toy 'project' of mine.  There exists a game
called BattleTech (which is a strategy boardgame of sorts; you control
some number of giant robots and attempt to blow up your opponent's giant
robots).  There exist optional rules for creating and managing a "military
division" of these giant robots, so you can use the same division from one
game to the next (keeping track of casualties, logistics, etc.)  I decided
to write a progam, in Lisp, for fun, that would handle the rules of
creating and managing a division, since it can be rather tedious and
involve a lot of accounting (perfect job for a computer to do).  In the
midst of creating this app, I realized that there were different ways to
view the individual units of the division.  The most "obvious" way to
distinguish units was by class, where class was robot, conventional
vehicle, aircraft, infantry, and so on.  But in some instances, it made
more sense to specialize methods based upon maneuvering systems (tracked,
wheeled, VTOL, hover, bipedal, quadrupedal), other times based upon
technology level (fusion engines or internal combustion), still other
times based on mode of operation (assault, fire support, recon), and so
on. 

From there I decided what would be more interesting would be to see if I
could create a system for allowing the "class" of an object to depend on
some context under which operations were being performed upon the object. 
I don't know if the class structure of CLOS itself is appropriate for this
goal, since in this system "class" becomes a very dynamic property that
can change whenever context changes (which is perhaps not well-suited to
OO and thus should not be part of the class hierarchy or method dispatch).
I then thought perhaps there needn't be any formal definition of "context
sensitive-class", and instead could just specialize methods based on the
content of the objects passed to them.  Thus, when I wanted to specialize
methods based upon the movement system of a unit, I could simply
specialize on the "movement-system" slot of the object passed as a parm,
and when I wished to specialize based on mode of operation I could either
specialize on some "mode-of-operation" slot, or specialize on some
combination of slots.

Providing subclasses and mixin-classes for the abundance of different
"classes" that I'd like to specialize on would... I don't know if it would
be a good idea, since it could result in a class-hierarchy with an
overabundance of classes.  Furthermore, any new "context" that I wished to
view objects under could result in me having to create new mixins and
update all classes in the hierarchy.

The wrapper cliche/idiom would definitely work, but... I thought that if I
were to be doing this often, that it would be better to have some sort of
well-defined, repeatable system of doing it.  As I understand it,
defgeneric basically creates a generic-function object as well as a
wrapper function which contains code that identifies the type or class of
the parms and calls the appropriate method based on that type or class
(the methods being objects stored within the generic-function object).  It
would seem then, that what I would end up doing would be similar (though
simpler) than what defgeneric does.

Thus, finally, the thought that perhaps CLOS provides some way to ... do
all of this, even though it doesn't seem to be covered explicitly in AMOP.

I dunno if any of this long-winded explanation will help at all; nor do I
know if there is really any interest in CLOS anyway (the last version of
PCL was released in... 92?; c.l.clos is trafficless; very very few books
on the subject that I've seen anyway...)

Thanks again
--steve
From: Barry Margolin
Subject: Re: CLOS Help: custom parameter specializers for methods?
Date: 
Message-ID: <hozt.37$7t1.872776@cam-news-reader1.bbnplanet.com>
In article <············@bigboote.WPI.EDU>,
Steve Lawler <········@WPI.EDU> wrote:
>From there I decided what would be more interesting would be to see if I
>could create a system for allowing the "class" of an object to depend on
>some context under which operations were being performed upon the object. 
>I don't know if the class structure of CLOS itself is appropriate for this
>goal, since in this system "class" becomes a very dynamic property that
>can change whenever context changes (which is perhaps not well-suited to
>OO and thus should not be part of the class hierarchy or method dispatch).
>I then thought perhaps there needn't be any formal definition of "context
>sensitive-class", and instead could just specialize methods based on the
>content of the objects passed to them.  Thus, when I wanted to specialize
>methods based upon the movement system of a unit, I could simply
>specialize on the "movement-system" slot of the object passed as a parm,
>and when I wished to specialize based on mode of operation I could either
>specialize on some "mode-of-operation" slot, or specialize on some
>combination of slots.

The traditional OO way of doing this is for the slot to contain an object
of an appropriate class.  You then send a message to the slot contents,
telling it to do something, and it specializes appropriately.  Often you'll
pass the containing object as a parameter in the message call, so that the
object can send messages back to its container (although in some
applications there's a one-to-one correspondence between container and
containee, and the containee has a slot of its own containing the
container, so you don't need to pass it explicitly).

This is essentially how you would do it in CLOS, as well, although CLOS
allows the contents to be an object compared with EQL rather than a CLOS
instance.  So it's basically isomorphic to one of the schemes you said you
didn't like:

(defmethod <operation> ((parm <type>) (contents (eql <symbol>)) ..) ...)

I don't think there's really anything easier than this.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
Support the anti-spam movement; see <http://www.cauce.org/>
Please don't send technical questions directly to me, post them to newsgroups.
From: Thomas A. Russ
Subject: Re: CLOS Help: custom parameter specializers for methods?
Date: 
Message-ID: <ymioh1g5k8x.fsf@sevak.isi.edu>
Actually, the sorts of behavior and organization of information that
you are describing is what AI knowledge representation research has been
concerned with for many years.  One branch of that field,
classifier-based knowledge representation (sometimes also called
"description logic" now) has dealt with that extensively.

There are several key differences between such a description logic
system and other object-oriented systems.  The two most prominent are
that instances can belong to multiple concepts (classes) at the same
time and the use of instance classificatino.

The idea of multiple-inheritance is extended to the instance level.
This is particularly useful if there are a number of orthogonal ways of
splitting the up the organization of instances.  In CLOS, one would need
to create (in advance) all of the conjunctions of classes that an
instance could belong to.  In a description logic, that isn't necessary,
since that conjunction can be handled simply by asserting class
membership.

Instance classification relies on the ability to write "definitions" of
what it means to belong to a particular class.  Such definitions can
refer to the values of slots.  That means it would be relatively easy to
define something like "robot that is low on fuel" using a construct
like:

  (defconcept (robot-low-on-fuel ?r)
    :is (and (robot ?r) (< (current-fuel ?r) (* .1 (maximum-fuel ?r)))))

This would define a concept that is satisified for all robots which have
less than 10% of their fuel remaining.  A reasoner called the classifier
exists which monitors changes in the current-fuel slot (and also
maximum-fuel, but I assume that that doesn't usually change).  When the
current-fuel declines enough to match this concept definition, the
classifier is able to automatically conclude that the instance belongs
to the concept (class) ROBOT-LOW-ON-FUEL.



Disclaimer:  I have a direct interest in such systems because I am one
of the implemetors of Loom, a particular example of a description logic
system.  For more information, you can look at 

      http://www.isi.edu/isd/LOOM/


-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Howard R. Stearns
Subject: Re: CLOS Help: custom parameter specializers for methods?
Date: 
Message-ID: <34BBE145.15FE@elwood.com>
Looking purely at the CLOS engineering angle and not at the general
programming issue of whether these are the best ways to approach the
problem....

1. You need not NECESSARILY worry about combinatorial explosion of
classes. I believe that CLIM implementations define a huge number of
mixins and then define the instantiable classes as they are needed by
the application.  For example, define classes behavior-a, behavior-b,
behavior-c, ... . Then, the application itself can define classes at
runtime that have, say, behavior-a, behavior-b and behavior-z as
superclasses.  Later, a program might need to create a class that has
only behavior-c.  Thus you will have only as many classes defined as are
actually needed, and not have to define all the combinations ahead of
time.

2. In CLOS you can dynamically change the class of an object.  Maybe it
starts out as a regiment-with-fast-transport and latter becomes a
depleted-pinned-down-regiment-with-a-field-hospital.  You can use
change-class, etc. to change the class of existing, already instantiated
objects, and can control how differing slots get updated, combined,
deleted, etc. 

3. If you really need to come up with a new dispatching scheme, the
MetOabject Protocol (MOP) does support this.

For more information about the MOP, see 
 http:/www.elwood.com/alu/table/references.htm#mop
including links to the book publishing info on "AMOP" and a releated
book, a hypertext of the CLOS MOP spec, the Xerox home page of the
researchers, etc.

These give examples of how to use the capabilities described above.


Steve Lawler wrote:
> 
> Barry Margolin (······@bbnplanet.com) wrote:
> :
> : Perhaps you could reconsider the design that caused this requirement.  Why
> : are you putting this tag in a slot, rather than making empty-buffer,
> : non-empty-buffer, and almost-full-buffer subclasses or mixin classes?
> 
> Well... this started from a toy 'project' of mine.  There exists a game
> called BattleTech (which is a strategy boardgame of sorts; you control
> some number of giant robots and attempt to blow up your opponent's giant
> robots).  There exist optional rules for creating and managing a "military
> division" of these giant robots, so you can use the same division from one
> game to the next (keeping track of casualties, logistics, etc.)  I decided
> to write a progam, in Lisp, for fun, that would handle the rules of
> creating and managing a division, since it can be rather tedious and
> involve a lot of accounting (perfect job for a computer to do).  In the
> midst of creating this app, I realized that there were different ways to
> view the individual units of the division.  The most "obvious" way to
> distinguish units was by class, where class was robot, conventional
> vehicle, aircraft, infantry, and so on.  But in some instances, it made
> more sense to specialize methods based upon maneuvering systems (tracked,
> wheeled, VTOL, hover, bipedal, quadrupedal), other times based upon
> technology level (fusion engines or internal combustion), still other
> times based on mode of operation (assault, fire support, recon), and so
> on.
> 
> From there I decided what would be more interesting would be to see if I
> could create a system for allowing the "class" of an object to depend on
> some context under which operations were being performed upon the object.
> I don't know if the class structure of CLOS itself is appropriate for this
> goal, since in this system "class" becomes a very dynamic property that
> can change whenever context changes (which is perhaps not well-suited to
> OO and thus should not be part of the class hierarchy or method dispatch).
> I then thought perhaps there needn't be any formal definition of "context
> sensitive-class", and instead could just specialize methods based on the
> content of the objects passed to them.  Thus, when I wanted to specialize
> methods based upon the movement system of a unit, I could simply
> specialize on the "movement-system" slot of the object passed as a parm,
> and when I wished to specialize based on mode of operation I could either
> specialize on some "mode-of-operation" slot, or specialize on some
> combination of slots.
> 
> Providing subclasses and mixin-classes for the abundance of different
> "classes" that I'd like to specialize on would... I don't know if it would
> be a good idea, since it could result in a class-hierarchy with an
> overabundance of classes.  Furthermore, any new "context" that I wished to
> view objects under could result in me having to create new mixins and
> update all classes in the hierarchy.
> 
> The wrapper cliche/idiom would definitely work, but... I thought that if I
> were to be doing this often, that it would be better to have some sort of
> well-defined, repeatable system of doing it.  As I understand it,
> defgeneric basically creates a generic-function object as well as a
> wrapper function which contains code that identifies the type or class of
> the parms and calls the appropriate method based on that type or class
> (the methods being objects stored within the generic-function object).  It
> would seem then, that what I would end up doing would be similar (though
> simpler) than what defgeneric does.
> 
> Thus, finally, the thought that perhaps CLOS provides some way to ... do
> all of this, even though it doesn't seem to be covered explicitly in AMOP.
> 
> I dunno if any of this long-winded explanation will help at all; nor do I
> know if there is really any interest in CLOS anyway (the last version of
> PCL was released in... 92?; c.l.clos is trafficless; very very few books
> on the subject that I've seen anyway...)
> 
> Thanks again
> --steve