[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Issue: DEFPACKAGE (version 2)
Issue: DEFPACKAGE
References: CLtL section 11.7.
Category: ADDITION
Edit history: Version 1, 12-Mar-88, Moon
Version 2, 23-Mar-88, Moon, changes based on discussion
Problem description:
The package functions included in CLtL encourage a programming style
that tends to evoke the worst aspects of the package system. The
problem is that if the definition of a package is scattered through
a program, as a number of individual forms, it is very easy to read
a symbol before the package setup needed to read that symbol correctly
has been accomplished. Three examples: an inherited symbol that should
have been shadowed might be accessed; a single-colon prefix might be
used for a symbol that will later be exported, causing an error; a local
symbol might be accessed where a symbol that will later be imported or
inherited was intended. These problems can be difficult to understand
or even to recognize, are difficult to recover from without completely
restarting the Lisp, and give Common Lisp a bad name.
Proposal (DEFPACKAGE:ADDITION):
Add a DEFPACKAGE macro to the language. It encourages putting the
entire definition of a package in a single place. It also encourages
putting all the package definitions of a program in a single file, which
can be loaded before loading or compiling anything that depends on those
packages. This file can be read in the USER package, avoiding any
package bootstrapping issues.
In addition, DEFPACKAGE allows a programming environment to process
the whole package setup as a unit, providing better error-checking and
more assistance with package problems, by dint of global knowledge of
the package setup.
Also expand MAKE-PACKAGE and IN-PACKAGE to take all the same keyword
arguments as DEFPACKAGE, for consistency.
The syntax of DEFPACKAGE is
(DEFPACKAGE package-name {option}*)
where each option is a list of a keyword and arguments. Nothing in a
DEFPACKAGE form is evaluated.
package-name is a symbol or a string; if a symbol, only its name
matters, not what package it is in. If a string, capitalization
matters, normally uppercase is used.
Standard options for DEFPACKAGE are listed below. Additional options
might be present in an implementation, and each implementation must
signal an error if an option not recognized by that implementation is
present. Additional implementation-dependent options might take the
form of a keyword standing by itself as an abbreviation for a list
(keyword T); this syntax should be properly reported as an unrecognized
option in implementations that do not support it.
Each option may appear at most once. If duplicate options are present,
DEFPACKAGE signals an error.
(:EXPORT {symbol}*)
Create symbols with the specified names and export them.
Note that only the name of each argument symbol is used.
The symbol that gets exported is not necessarily the one given
as an argument; it's a symbol with that name but in the package
being defined.
(:IMPORT {symbol}*)
Import the specified symbols.
(:IMPORT-FROM {(package-name {symbol}*)}*)
(:IMPORT-FROM package-name {symbol}*)
Find the specified symbols in the specified packages and import
them into the package being defined. The second syntax is a
convenient abbreviation when only one package is specified.
Note that only the name of each argument symbol is used. The
actual symbol that gets imported is not necessarily the one
given as an argument; it's a symbol with that name accessible in
the named package.
(:NICKNAMES {package-name}*)
Set the package's nicknames to the specified strings.
(:SHADOW {symbol}*)
Create the specified symbols in the package and place them on
the shadowing list. Note that only the name of each argument
symbol is used.
(:SHADOWING-IMPORT {symbol}*)
Import the specified symbols into the package and make them
shadow any inherited symbols.
(:SHADOWING-IMPORT-FROM {(package-name {symbol}*)}*)
(:SHADOWING-IMPORT-FROM package-name {symbol}*)
Find the specified symbols in the specified packages and import
them into the package being defined, making them shadow any
inherited symbols. The second syntax is a convenient
abbreviation when only one package is specified. Note that only
the name of each argument symbol is used. The actual symbol
that gets imported is not necessarily the one given as an
argument; it's a symbol with that name accessible in the named
package.
(:SIZE integer)
Declare the approximate number of symbols expected in the package.
(:USE {package}*)
Inherit from the specified packages.
Example:
(DEFPACKAGE MY-PACKAGE
(:USE LISP)
(:SHADOW CAR CDR CONS)
(:NICKNAMES MYPKG MY-PKG))
Rationale:
See first paragraph of Proposal section.
Current practice:
Symbolics Common Lisp has always had this, and uses it in preference
to individual calls to EXPORT, IMPORT, SHADOW, etc. The SCL version
of DEFPACKAGE has quite a few additional options, but none of them
appear to be necessary to propose for Common Lisp at this time.
Cost to Implementors:
Should be small as the macro can be implemented simply as a bunch of
calls to existing functions.
Cost to Users:
No cost, this is upward compatible.
Cost of non-adoption:
Packages continue to be difficult to use correctly.
Benefits:
Guide users away from using packages in ways that get them into trouble.
Esthetics:
Neutral.
Discussion:
The "Put in seven extremely random user interface commands" business
described at the end of chapter 11 could be removed, and the special
compiler handling of these functions necessary to support that could be
removed. As this would be an incompatible change, it is not part of
this proposal.
KMP suggests that IN-PACKAGE should be incompatibly changed only to
recognize existing packages, not to create them, which would fix a lot
of bugs. IN-PACKAGE would then not accept any keyword arguments.
Moon thinks this is a reasonable idea but should be the subject of a
separate proposal.