[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Packages: a modest solution.

Aha!  I finally figured out the solution to the package problem!

I believe inclusion of packages is the worst mistake in Common LISP's
design.  There isn't a day goes by (when I actually get to program or
debug) when I don't have package problems.  Often, they dominate the
debugging time.  I now type <pkg>::<symbol> all the time, just so I don't
have to think about whether the reader can figure out the right default.  I
truly miss the days when a symbol was a symbol--surely one of the most
elegant features of Lisp 1.0 that's been lost.

But, of course, almost everyone feels this way.  They just don't know how
to get around the problems packages seem to solve.  Actually, I believe
that object-oriented programming generic functions solve about half the
problems packages are meant to solve; but they're not in Common LISP yet.

Everyone also realizes that the "mistake" is in tying package determination
to the reader.  The reader simply has so little context that to determine
where a symbol belongs has to be done very stupidly.  The solution
ultimately has to be a combination of the following:

   * determining the appropriate package becomes trivial, unnecessary or
     meaningless (keywords, generic functions, English commentary, 
     lexically scoped variables and functions(!), or symbols with
     explicitly provided package names);

   * more sophisticated programs determine the package after reading has
     occurred (during a sort of "package expansion" phase); i.e., admit
     that Lisp has a parser.

It is worth noting that the former category constitutes the bulk of the
symbols used in programs, and that getting these symbols in the "wrong"
package is the source of so much frustration and futility.

To move toward this future world, in which package determination becomes
decoupled from the reader, we simply need to make UNINTERNED symbol be the
MOST common symbol to be used.  The reader must be able to be told not to
use default package.  A solution might be to allow the read function to be
passed a package determiner function, as an optional (keyword) argument.
The determiner takes the result from read (uninterned symbols when no
package was explicitly given via : or :: and a symbol was read) and returns
the package expanded expression.  

Notice, I am not assuming that reading a symbol is the only result of read.
In particular, the intelligent determination of packages comes from calling
the package determiner on S-expressions returned by the reader (full of
uninterned symbols and symbols with explicitly specified packages).  I'm
not claiming that it will be easy to write such functions (if it were,
having the reader itself determine the package might be easy); I'm simply
claiming that it's worth it!

This must be defined carefully.  At first blush, it may seem that the
reader should not invoke the package expander in a bottom up fashion.  Only
the top level expression should be given to the expander.  Then the
expander could be allowed to smash structure.  This assumes no read macros
return previously defined structure (an invalid assumption, generally).
Alternatively, perhaps the expander should be called on every
sub-expression,  with an extra argument indicating whether the top level
expression is being passed.  Clearly, the reader should be able to assume
that if an uninterned symbol is determined to mean an interned symbol that
the uninterned symbol can be deleted if it just created it...

Present implementations of uninterned symbols cannot support this
determiner idea well.  To support this, uninterned symbols should print out
very normally, perhaps in lower case without bars, instead of #:....  These
symbols should be full-fledged symbols with values and function cells.
Obviously, I am proposing that they not be syntactically distinguishable
from interned symbols.  Should (MAKE-SYMBOL "a") be EQ to itself (it isn't
on Symbolics implementations).  Is there any other way to create the
uninterned symbol with that name?


				Dave Wile

P.S.  I am looking for conventions that make packages easier to live with.
      Since I have converted code from an existing Interlisp implementation
      in which all my global symbols were prefixed, I found using explicit
      package prefixes on all exported symbols (for emphasis) whereever
      they occur to be convenient.  Naturally, I hid all the others and
      dropped the prefix.  Any other folklore on this?