From: jeff@aiai.edinburgh.ac.uk (Jeff Dalton)
Newsgroups: comp.lang.clos
Subject: Re: Alternative specializer types
Date: 8 Sep 92 15:10:28 GMT
Article-I.D.: subnode.9757.9209081510
Organization: The Ohio State University Department of Computer and Information Science

> In an application I'm developing, it would be very useful to allow my
> methods to have specializers different than the standard class or eql
> specializers, but it's not clear whether the AMOP supports it.  In
> particular, I would like to have a class of methods that can use
> "AND" specializers, as in:
> 
> (defmethod foo ((self (and class1-mixin class2-mixin))) ...)
> 
> I need this because class1-mixin and class2-mixin can be used
> independently of each other, but when used together require a
> completely different algorithm for foo.  I could, of course, create
> a class1-and-class2-mixin class that inherits both and does what is
> necessary.  However, I'm trying to design my class hierarchy so that
> users can build their classes out of whatever mixins they need, without
> having to worry about their potential interdependencies (e.g. knowing
> they have to include a class1-and-class2-mixin).

You might try something that automaticaly generates the intersection
classes given a list of the classes to include.  This is more or less
the idea behind the "mixin servers" in OakLisp and the :mixin option
in ZetaLisp Flavors.  Anyway, here's something about it that I sent
a while ago to the EuLisp group:

The basic idea is that you can ask for a class with certain mixins,
and one will be created if one does not already exist.

There are two points where you might ask for such a class: when you
want the class (Oaklisp) and when you make an instance (Flavors).

The :MIXTURE option in DEFFLAVOR let's you specify the certain values
for initargs are requests for certain classes to be mixed-in.  It
looks like this:

   (:mixture (:input input-mixin)        ;if :input is t
             (:output output-mixin)      ;if :output is t
             (:direction
                (:in input-mixin)        ;if :direction is :in
                (:out output-mixin)))    ;if :direction is :out

Suppose this option were on the definition of the STREAM flavor.
Then

   (make-instance 'stream :direction :in)

would make an instance of a flavor with direct components INPUT-MIXIN
and STREAM.

The Oaklisp "mixin servers" were described in a message to
Comp.lang.scheme:

---------------------------
Date: 6 Feb 92 01:35:33 GMT
From: Scott Draves <spot@cs.cmu.edu>
Organization: School of Computer Science, Carnegie Mellon University
Subject: Extending Scheme+++
Message-Id: <SPOT.92Feb5203533@WOOZLE.GRAPHICS.CS.CMU.EDU>
To: scheme@mc.lcs.mit.edu

several people have mentioned T as an example of a Scheme with
user-level datatypes.  I'd just like to mention another: Oaklisp.  I
include below two chapters of its manual, and its implementation of
lazy-cons.  you can ftp the manual and an implementation from
a.gp.cs.cmu.edu:/afs/cs/misc/oaklisp/build (cd directly to this
directory, not any intermediate ones). This stuff is Copyright (C)
1988 Barak Pearlmutter and Kevin Lang.  For the full license, see the
sources.

[...]

\section{Mixing Types}

Frequently, type hierarchies become so rich that they threaten to
overwhelm users with a plethora of possible combinations of mixins.
The combinatorial explosion of the number of possible concocted types
seems intrinsic to the style of programming involving multiple
functionally orthogonal mixins.  Above a certain level of complexity,
finding a type with certain known characteristics can become
difficult.  Programmers are left wondering ``Has a type based on {\em
foo} with {\em bar, baz} and {\em zonk} mixed in been created, if so
what's its name, and if not what should I name it and where should I
define it?''

Oaklisp's {\em mixin managers} take care of this problem.  When one
needs ``the type based on {\em foo} with {\em bar, baz} and {\em zonk}
mixed in,'' one asks a mixin manager for it.  If such a type has
already been created, it is returned; if not, the mixin manager
creates an appropriate new type, caches it, and returns it.  This
eliminates the burden of remembering which types have been concocted
and what they are named.

\op{mix-types}{mixin-manager type-list}
\doc{This returns a composite type whose supertypes are {\em
type-list}.  {\em Mixin-manager} checks its cache, and if the
requested type is not found it creates a type with {\tt (make type '()
{\em type-list})}, caches it, and returns it.}

\ty{mixin-manager}
\doc{Instances of this cache composite types, acting as a sort of
composite type library.}

The Oaklisp operation type hierarchy is quite elaborite, containing a
large number of functionally orthogonal mixins, and therefore the
Oaklisp internals make heavy use of the mxin manager facility when
dealing with operations.  For example, the following definition for
\df{+} is drawn from deep within the bowels of Oaklisp.
\begin{verbatim}
(define-constant-instance +
  (mix-types oc-mixer
             (list foldable-mixin open-coded-mixin operation)))
\end{verbatim}

----------------------------------------------------------------------

-- jeff