[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Issue: DEFPACKAGE (version 3)
- To: Moon@STONY-BROOK.SCRC.Symbolics.COM
- Subject: Issue: DEFPACKAGE (version 3)
- From: Jon L White <jonl@lucid.com>
- Date: Tue, 27 Sep 88 22:41:16 PDT
- Cc: CL-Cleanup@Sail.stanford.edu
- In-reply-to: David A. Moon's message of Tue, 27 Sep 88 00:04 EDT <19880927040452.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
- Site:
re: ... why don't you just write up the proposal your way, leaving out
arguments comparing it with the previous proposal, and then I will
either criticize it constructively or accede to it.
Well, ok, but all I really wanted to do was to get consensus on the one
point of removing :IMPORT and :SHADOWING-IMPORT.
Here is your version 2 from 23-Mar-88 with that deletion, and with the
following emmendations, all of which are minor except for (3):
(1) "symbol" --> "symbol-name" in numerous places, as per your mail
message of "Date: Fri, 20 May 88 22:12 EDT"; also added appropriate
commentary about depending only the "name", not the symbol.
(2) Specify that :IMPORT-FROM (and :SHADOWING-IMPORT-FROM) signals an
error if any of the specified symbols do not already exist in the
"from" package.
(3) Explicitly permit EXPORT to work after the other options, so that
it can apply to imported and inherited symbols, as well as to
absolutly fresh ones; this is new -- I hope you can agree to it, or
give constructive criticism.
(4) Added, and updated, references to Issues IN-PACKAGE-FUNCTIONALITY
and PROCLAIM-ETC-IN-COMPILE-FILE; also added my "support" for the
former into the Discussion section.
(5) Added an alternate form under Examples; added "canonicalization"
comment to Discussion.
(6) Re-order the presentation of the options to accord with a revised
order for the "7 Extremely Randoms" of CLtL p191 [not very important].
-- JonL --
!
Issue: DEFPACKAGE
References: CLtL section 11.7.
Issue: IN-PACKAGE-FUNCTIONALITY
Category: ADDITION
Edit history: Version 1, 12-Mar-88, Moon
Version 2, 23-Mar-88, Moon, changes based on discussion
Version 3, 27-Mar-88, JonL
(remove :import, :shadowing-import; allow :export to work on
imported and inherited; update references to in-package, etc.)
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, unless the cleanup Issue
IN-PACKAGE-FUNCTIONALITY is adopted) 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.
(:NICKNAMES {package-name}*)
Set the package's nicknames to the specified names.
(:USE {package-name}*)
Inherit from the specified packages.
(:SHADOW {symbol-name}*)
Create the specified symbols in the package being defined, and
place them on the shadowing symbols list. Each 'symbol-name'
argument must be either a string or a symbol. If given as a
symbol, only its name is used; and in this case the shadowing
symbol entered into the package being defined is definitely not
the one given as argument, but rather a symbol of the same name
freshly created as a shadow in the package.
(:SHADOWING-IMPORT-FROM {(package-name {symbol-name}*)}*)
(:SHADOWING-IMPORT-FROM package-name {symbol}*)
Find the specified symbols in the specified packages and import
them into the package being defined, and place them on the
shadowing symbols list. Each 'symbol-name' argument must be
either a string or a symbol. If given as a symbol, only its
name is used; and in this case, the symbol that is imported is
not necessarily the one given as an argument, but rather the symbol
of that name accessible in the "from" package. In no case will
symbols be created in any package other than the one being defined;
a continuable error is signalled if no symbol is accessible for
one of the names in its corresponding "from" package. The second
syntax is simply a convenient abbreviation when only one package
is specified.
(:IMPORT-FROM {(package-name {symbol-name}*)}*)
(:IMPORT-FROM package-name {symbol-name}*)
Find the specified symbols in the specified packages and import
them into the package being defined. Each 'symbol-name' argument
must be either a string or a symbol. If given as a symbol, only
its name is used; and in this case, the symbol that is imported is
not necessarily the one given as argument, but rather the symbol
of that name accessible in the "from" package. In no case will
symbols be created in a package other than the one being defined;
a continuable error is signalled if no symbol is accessible for
one of the names in its corresponding "from" package. The second
syntax is simply a convenient abbreviation when only one package
is specified.
(:EXPORT {symbol-name}*)
Find or create symbols with the specified names and export them.
Each 'symbol-name' argument must be either a string or a symbol.
If given as a symbol, only its name is used; and in this case,
the symbol that is made external in the defined package is not
necessarily the one given as an argument, but rather a symbol of
that name freshly interned in the package being defined. Note an
interaction with the :USE option, since intern'ing may inherit
symbols rather than creating new ones; note also an interaction
with the :IMPORT-FROM and :SHADOWING-IMPORT-FROM options, since
intern'ing will merely access an already imported symbol.
(:SIZE integer)
Declare the approximate number of symbols expected in the package.
This is an efficiency hint only, so that the package's table will
not have to be frequently re-expanded when new symbols are added
to it (e.g., by reading in a large file "in" that package.)
The collection of symbol-name arguments given to the options :SHADOW,
:IMPORT-FROM, and :SHADOWING-IMPORT-FROM must all be disjoint; an error
is signalled otherwise. In a chronological sense, the :EXPORT may be
thought of as ocurring last so that it can make reference to inherited
or imported symbols already created by the other three options.
Examples:
;;; Play it super-safe, and use only strings as names; do not even assume
;;; assume that the package it is read in to "uses" LISP; do *not* create
;;; any symbols whatsoever in the package that it is read in to.
(LISP:DEFPACKAGE "MY-PACKAGE"
(:NICKNAMES "MYPKG" "MY-PKG")
(:USE "LISP")
(:SHADOW "CAR" "CDR")
(:SHADOWING-IMPORT-FROM "VENDOR-COMMON-LISP" "CONS")
(:IMPORT-FROM "VENDOR-COMMON-LISP" "GC")
(:EXPORT "EQ" "CONS" "FROBOLA")
)
;;; A similar call, using symbols rather than strings as names; expects
;;; to be read in to a package that "uses" LISP, and *may* create
;;; random internal symbols in that package (such as MY-PACKAGE etc).
(DEFPACKAGE MY-PACKAGE
(:NICKNAMES MYPKG :MY-PKG)
(:USE LISP)
(:SHADOW CAR :CDR #:CONS)
)
Rationale:
See first paragraph of Proposal section.
Current practice:
Symbolics Common Lisp has always had a DEFPACKAGE, 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" mnemonic
described in CLtL p.191 could be removed, and the special compiler
handling of these functions necessary to support that could be removed
(except possibly for REQUIRE and PROCLAIM -- see the Issue
PROCLAIM-ETC-IN-COMPILE-FILE). As this would be an incompatible change,
it is not part of this proposal.
The issue IN-PACKAGE-FUNCTIONALITY recommends that IN-PACKAGE be
incompatibly changed to recognize only existing packages, not to create
them. IN-PACKAGE would then not accept any keyword arguments.
Moon (and JonL and KMP) thinks this is a reasonable idea, and is the
subject of a separate proposal.
The macroexpansion of DEFPACKAGE should be permitted to canonicalize
into the strings-as-name form, so that even though the source file
showed random symbols in the DEFPACKAGE form, the compiled file might
have only strings in it.