[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
- To: Kent M. Pitman <KMP at MIT-MC>
- Subject: Packages
- From: MOON at SCRC-TENEX
- Date: Wed, 11 May 1983 02:19:00 -0000
- Cc: Common-Lisp at SU-AI
- In-reply-to: The message of 10 May 1983 18:09 EDT from Kent M. Pitman <KMP @ MIT-MC>
Date: 10 May 1983 18:09 EDT
From: Kent M. Pitman <KMP @ MIT-MC>
I'd like to respond to this at length since I think I understand all this stuff now.
(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.
This is precisely why I suggested it. The internal-symbol qualified name syntax
is very rarely used, and if it is used in a program the programmer is almost
certainly doing something wrong, probably due to a misunderstanding. So I
thought it was a good idea for it to be ugly.
* "#" is defined as a token terminator. This would have to be redefined.
I note (p219, Colander Edition -- sorry; I have no Laser edition)
It's unfortunate that you weren't sent a Laser edition; this was fixed at the
discussion meeting in Pittsburg last August.
* 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.
I can't make any sense of this. #: is no more and no less hairing up the
language syntax than : itself is.
* If "#:" is used to mark symbols with no package cell, it is overloaded
and visually misleading to have it mean both things.
I don't think so; certainly no more than dot is overloaded. Before a symbol
and inside of a symbol are just different, that's all.
(2) I dislike visually marking symbols that have no package cell.
This was agreed upon in August. Again it's unfortunate that you never saw a
Laser edition manual. But if we go back and argue over everything we've done
in the past year we'll never get this language defined. Doubly unfortunate
that you never saw the quotation from the Federalist papers in the front of
the laser edition. As it happens I don't much like marking uninterned symbols
specially myself, but I'm not going to quarrel over it. Easy enough to
put in a *prinfoo* flag to turn it off it really irritates.
* 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".
This just means that you're one of the large community of users who will
always run with *princircle* set to t, commendably preferring correctness
over efficiency. This doesn't have much to do with packages, or even symbols,
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
Since inheriting is "by reference" rather than "by value", this can't
happen. The inherited symbol isn't accessible if it gets uninterned from
the place it is being inherited from. This is important.
But perhaps you really meant to say "imported." You are right about
this misfeature, which was mentioned in Fahlman's documentation. Removing
the flagging of uninterned symbols would hardly fix this misfeature, it
would simply obscure it somewhat, since now you would have "perfectly
valid symbols" that would print without a package prefix when they should
have had a prefix. The only advice I can give is if you move a symbol from
one package to another and forget to setf the symbol-package to the new
package, then you forgot something.
I guess the following properties are relevant ...
(a) Symbols which were EQ before a PRINT-READ cycle should be EQ
(b) Symbols which were not EQ before a PRINT-READ cycle should not be
(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 can't think of any examples of cases where it is at all difficult to assure.
Can you supply one?
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).
Again, *princircle* is the answer to this. Of course it can only work within
a single form, so it isn't a complete answer, which by the very definition of
interning is impossible.
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.
Maybe. That depends on whether prefixes and infixes are considered to be
the same by most people.
(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.
Correcting your typo of USE-PACKAGE when you meant INCLUDE-PACKAGE, this
scenario is exactly why I pointed our in my comments the need for more
comprehensive handling of name clashes. The order of searching ancestors
cannot be allowed to make a difference if we are to remain sane.
(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; ..."
The wording probably needs to be clarified. I think Fahlman's intention was
that the terms "internal" and "external" were to be taken as mutually exclusive.
Internal is synonymous to neither "accessible" nor "present".
(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?
In the Lisp machine, this was recently corrected by introducing a new special
form (macro), SETQ-GLOBALLY, along with accompanying functions SET-GLOBALLY,
SYMEVAL-GLOBALLY, MAKUNBOUND-GLOBALLY. These operate on the global value of
a dynamic variable, regardless of any bindings that may currently be in effect.
They are slow. SETQ-GLOBALLY is also undoable. I hesitate to propose these
for Common Lisp right now while we are in a rush to get a consistent, stable,
documented language that we can all implement and use as a basis for future
(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?
Fahlman wanted to keep the proposal simple so yes there is only one
namespace of package names and you aren't allowed to call the primitive
that creates a package object without giving it a name and linking it into
the data structure.
Packages are non-hierarchical so "rooted" makes no sense. Are anonymous packages
good for something?
I expect that on the Lisp machine there will be a provision for nicknames
to a package that are only recognized in qualified names and only when
*package* is one of certain other packages. This extension to Common Lisp
is good when renaming a whole group of related packages. This may be what
(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
(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.
This would be a good name but unfortunately the name that is consistent with
the other printer control flags is *PRINPACKAGE*. I proposed this at one
point and would still like to see it; after we agree on the basic package
system I will send a message containing a small list of non-controversial
extensions like this which I would like to see included in the standard
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.
Having more choices than T and NIL seems like a good idea here, although
I'm not sure that the full hair of a predicate would be used.
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
I don't understand this. What problem is solved by changing it from the
default state (:MAYBE ?) to :NEVER? No symbol you can type in without
a package prefix will be printed back out with one.