From: Scott Simpson
Subject: Using Packages With CLOS
Date: 
Message-ID: <26B09E74.58E0@wilbur.coyote.trw.com>
How do people use packages with CLOS classes? The most obvious
solution to me would be to make a separate package for each class. My
office mate objected to this, saying that it would cause problems with
inheritance. He noted that symbols are local to a package and when you
inherit from another class you would need to know the superclasses
name to access any inherited slot. My retort was that you should
provide accessor functions for superclass slots in your class and
export them if you wish to enable the user of the class to access an
inherited slot. Then if you changed the superclass for any reason the
code behind the package wall would change but the accessor function
used by the user using the class would not change.
	Another issue is the mapping between file names and CLOS
classes. Do you normally create a different file for each CLOS class?
This seems to me to be simple method for quickly identifying where
classes are stored. If all the files are stored in the same directory,
it regrettably flattens the type hierarchy structure you are trying to
simulate but I think it is the best you can do without some sort of
object-oriented database underneath.
Scott Simpson    		TRW 			·····@coyote.trw.com
Scott Simpson    		TRW 			·····@coyote.trw.com
From: Barry Margolin
Subject: Re: Using Packages With CLOS
Date: 
Message-ID: <41113@think.Think.COM>
In article <·············@wilbur.coyote.trw.com> ·····@wiley.uucp (Scott Simpson) writes:
>How do people use packages with CLOS classes? 

I don't think there needs to be a particular relationship between classes
and packages.  The purpose of packages is to prevent inadvertant name
collisions between programs written by different groups of people.  They
can also be used to collect together all the public interfaces to a
facility.

>					       The most obvious
>solution to me would be to make a separate package for each class. 

This is probably too extreme.  A decent-sized application would probably
have dozens of classes, many of which are expected to be mixed together.
Related classes would be implemented by the same developer or development
team, so name collisions are not likely to be a problem.  They'd probably
end up using package prefixes excessively.  When a method is implemented by
several classes, or a normal function is needed by several classes, you'll
have to decide arbitrarily which class's package to use.  And packages can
be pretty confusing, and a large number of small packages is likely to
cause more problems than it solves.

Implementation of mixins can be tough with this scheme.  Frequently, a
mixin is designed so that it may be mixed in with any of a number of base
classes.  It simply requires that the instantiated subclasses implement a
given set of generic functions and/or provide a specified set of slots.  If
each base class is in its own package this can be problematic.

>								    My
>office mate objected to this, saying that it would cause problems with
>inheritance. He noted that symbols are local to a package 

Except, of course, for the ones that are exported and inherited or
imported into another package.  There's nothing special about the symbols
used to name slots and methods, so you can import and export them just like
any other symbols.  However, care must be taken in deciding what symbols to
export, since the export list defines the interface to a facility, and slot
names are not usually chosen that carefully.

>							   and when you
>inherit from another class you would need to know the superclasses
>name to access any inherited slot. My retort was that you should
>provide accessor functions for superclass slots in your class and
>export them if you wish to enable the user of the class to access an
>inherited slot. Then if you changed the superclass for any reason the
>code behind the package wall would change but the accessor function
>used by the user using the class would not change.

This is a good point.  However, it's often important to distinguish between
interfaces intended to be used between related classes and interfaces
intended for external users of the class.  This can, of course, be done by
providing an additional class for external users, and importing/exporting
only the public interface from this class.  (Some OO languages provide more
explicit support for this distinction, such as C++'s "protected" slots and
methods.)

However, one reason for using function-style accessors rather than
SLOT-VALUE is to hide the fact that a value is implemented as a slot of a
particular class.  However, by using packages this way you force this
association to be explicit.  See my point above about choosing the package
of a generic function implemented by multiple classes.

>	Another issue is the mapping between file names and CLOS
>classes. Do you normally create a different file for each CLOS class?
>This seems to me to be simple method for quickly identifying where
>classes are stored. If all the files are stored in the same directory,
>it regrettably flattens the type hierarchy structure you are trying to
>simulate but I think it is the best you can do without some sort of
>object-oriented database underneath.

One of the features of CLOS is the ability to spread the implementation of
a class out.  In some cases it's useful to keep the methods of a class
together.  In other cases, though, it's useful to keep all the methods
implementing a particular generic function together.  For instance, if you
have an optional facility that works by adding functionality to a bunch of
classes.

In Lisp it is often less necessary to keep source files small than it is in
other languages.  Most Lisp environments are integrated with an editor, and
make it easy to incrementally recompile functions and methods.  Therefore,
the edit-compile-test cycle time is not usually a function of source file
size.  Therefore, if you have a number of related, small classes (mixins
tend to be pretty small) it may be easier if they are in the same source
file.

Many good Lisp environments provide automated mechanisms for finding the
source file of an identifier, so there's less need for an easy way to
guess.
--
Barry Margolin, Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar