[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Packages
- To: Common-Lisp @ SU-AI
- Subject: Packages
- From: Kent M. Pitman <KMP @ MIT-MC>
- Date: Tue, 10 May 1983 22:09:00 -0000
Here are my notes on CMUC:<FAHLMAN.SLISP>PACKAGE.MSS.108.
Summary
Item Importance Notes
(1) Medium Propose changing "FOO#:BAR" to "#:FOO:BAR".
(2) Large Propose flushing "#:" notation on symbols with NIL
in their package cell.
(3) Small Questioning use of PUSHNEW in USE-PACKAGE.
(4) Small Wording issue in definition of "UNEXPORT".
(5) Tiny Syntax in "DECLARE-PACKAGE".
(6) Medium Setting *PACKAGE*, etc in init files.
(7) Small LIST-ALL-PACKAGES and anonymous packages.
(8) Medium Adding an optional PACKAGE argument to IMPORT, etc.
(9) Medium Forcing symbols to print with[out] package prefixes.
-----
(1) I dislike "#:" in the middle of a name for several reasons.
* I think it is ugly. It visually breaks up the symbol in a bad way.
* "#" is defined as a token terminator. This would have to be redefined.
I note (p219, Colander Edition -- sorry; I have no Laser edition)
there are no non-terminating macro sequences in the attributes table. I
think this is wise from the point of view of novices. The presence of
initially defined non-terminating macro sequences would just further
complicate the knowledge of Lisp syntax a novice would need.
* I would prefer a prefix notation such as "#:FOO:BAR" rather than
"FOO#:BAR". (If not "#:", some other prefix dispatch.) Thinking ahead
to the multi-level packages for a moment, and given that package ids
are strings (not symbols), would one write "FOO#:BAR:BAZ" or
"FOO#:BAR#:BAZ" or ... I would prefer they lead off with an
identification that the symbol coming up will be an internal one
and then give a normal qualified reference. eg, you could define
#: to just bind some (unexported) variable
*COMPLAIN-ABOUT-INTERNAL-PACKAGE-REFERNCES* to NIL and re-call READ
without hairing up the language syntax.
* If "#:" is used to mark symbols with no package cell, it is overloaded
and visually misleading to have it mean both things.
(2) I dislike visually marking symbols that have no package cell.
* When writing symbols out to a file and reading them back in, there's
a high percentage of chance it really doesn't matter what package
they are read into. To take a simple example,
(READ-FROM-STRING (FORMAT NIL "~S"
(LET ((V (GENSYM))) `(LAMBDA (,V) ,V))))
won't even "work".
You'd expect this with gensyms but its more irritating if you've
inherited some symbol from another package and you've uninterned
the symbol from the source package. Suddenly, perfectly valid symbols
may appear as if "gensymed" and will lose this property of being
EQ.
I guess the following properties are relevant ...
(a) Symbols which were EQ before a PRINT-READ cycle should be EQ
afterward.
(b) Symbols which were not EQ before a PRINT-READ cycle should not be
EQ afterward.
(c) A symbol which was EQ to some other symbol not involved in
a PRINT-READ cycle should still be EQ to it after such a cycle.
Given that property (c) is in general very hard to assure, I still place
a higher priority on (a) than on (b). Printing symbols out with no
annotation will guarantee (a) but may violate (b). Printing symbols out
with the proposed "#:" marking (as I understand it) seems to violate
(a) while guaranteeing (b).
Further, I think people will see "#:" coming out before gensysms for ages
before they see the other case. I predict this will cause great debugging
confusion for people that don't understand the other cases where this can
happen and who have from many experiences come to associate "#:" with
gensyminess, not with the heuristic feature off of which it drives.
An organized plan for treating gensyms would be nice, but in the absence
of one (I don't think we have time for that now) I don't think that
marking things that appear to be gensyms.
As a minor issue, "#:" would then be free for use in item (1) above.
(3) I'm not sure about using PUSHNEW rather than PUSH after a DELETE
when calling things like USE-PACKAGE. It seems to me that users will
expect the most recent call to USE-PACKAGE to have priority. Imagine
a package A with an external symbol FOO on it. Imagine a package B
which does USE-PACKAGE A and then shadows FOO. Imagine some package C,
the writer of which notices that A:FOO isn't provided in B and who doesn't
realize that A is included in B. He might ask to USE-PACKAGE A and be
confused that A:FOO still isn't visible.
I'm not so much saying this should be changed as I'm curious why things
are supposed to happen as documented. Is there an alternative scenario
that makes mine look less important?
(4) "If @b[unexport] is given a symbol that is already available
as an internal symbol in the current package, it does nothing; ..."
I guess my view was that "external" symbols are in some sense a subset
of "internal" ones; ie, when working "internally" to a package, i expect
"external" symbols are available (and they are). I was surprised, then,
by this wording. Does it mean the same as, and would it be clearer as:
"If @b[unexport] is given a symbol that is already available
only as an internal symbol in the current package, it does nothing; ..."
(5) In DECLARE-PACKAGE's description , shouldn't you say @b[:nicknames],
etc. or @i[nicknames]. I should think @i[:nicknames] would be confusing.
(6) Re: LOAD binding *PACKAGE*
The LispM has a problem with init files. People like to call pkg-goto
and assign BASE,IBASE in their inits and find themselves thwarted by
implicitly bound variables. A popular way to circumvent this problem
is by doing (PROCESS-RUN-FUNCTION #'(LAMBDA () (SETQ IBASE 10.)), etc.
This seems pretty drastic. Will Common Lisp address this issue?
(7) Are packages always global, named objects? Will there be a provision for
anonymous packages or packages rooted elsewhere besides GLOBAL?
In such an event, should LIST-ALL-PACKAGES be constrained to return
even anonymous packages?
(8) IMPORT, EXPORT, etc. use the "current package". I would prefer to have
them take &OPTIONAL (PACKAGE *PACKAGE*) since I find it very ugly to write
(LET ((PACKAGE *PACKAGE*)) (IMPORT ...)) if I happen not to have that
package selected.
(9) There are occasionally times when one would like a symbol to be printed
with any package prefix unconditionally. Such is the case for APROPOS,
for example. I would like the method by which I can make this happen be
explicit. On the LispM, one resorts to binding PACKAGE to NIL or
(pkg-find-package "GLOBAL"), but these "solutions" lose awfully if you
get a breakpoint in those packages since you either end up finding you
have a bad value for package (and recursively losing) or not finding
that you do (and losing in other ways). Perhaps a variable
*FORCE-PACKAGE-PREFIXES* which could be set T/NIL. Better still, perhaps
a variable *PRINT-PACKAGE-PREFIXES* which could be set
:ALWAYS Always print package prefixes
:NEVER Never print package prefixes
:MAYBE Print package prefixes when not "obvious"
fn A one-arg predicate which returns T if the package prefix
should be displayed and NIL otherwise.
Setting it to :NEVER would be great when you want to do simple symbol
manipulation unrelated to Lisp variables without getting bogged down in
package I/O behavior. I have some applications where this would have been
very handy.
--kmp