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

Packages



    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,
though, really.

          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.

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 
                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 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
standardized extensions.

    (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
you want.

    (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.

I agree.

    (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
language.

							   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
        very handy.

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.