From: David McClain
Subject: Package Question
Date: 
Message-ID: <OX3P7.45$p97.35065@news.uswest.net>
Up to now I had the impression that packages were like sharable
namespaces -- contents protected from outside assault, unless explicit means
(like IN-PACKAGE) were used to alter their content.

But I found that by simply using a package inside another client package, I
could accidentally redefine an imported symbol for my own needs in the
client package -- and this redefinition actually redefines the used symbol
back in the original package -- without any warning!!

E.g.,

;; --------------------------------------
;; in parent file...

(defpackage "THING"
  (:export "DOIT"))

(in-package "THING")

(defun doit ()  15)

-----------------------------------------
;;; in client file

(defpackage "THING-USER"
   (:use "THING"))

(in-package "THING-USER")

(defun doit () 16)

;; -----------------------------------

Now if I go back to package "THING" and examine #'doit, I find that it has
the definition given to it
by the THING-USER package.

Now this seems a bit startling, especially since I received no warning about
redefining the doit symbol.
It would seem that barrel-loads of problems could occur downstream, as other
unsuspecting user packages get their expected behaviors modified by some
other unknowing client package.

I see in CLHS no mention of what the expected behavior is. In fact, the
whole issue of package definitions seems still up in the air.

Is this particular situation implementation dependent? Or is it the expected
behavior? And if so, shouldn't some kind of warning be issued? How is a
client package ever to know that it might be redefining some exported
symbol?

Cheers,

- DM

From: David McClain
Subject: Re: Package Question
Date: 
Message-ID: <h64P7.50$p97.37695@news.uswest.net>
... Actually, I think that points to the danger inherent in just blindly
USE'ing a package instead of making explicit imports. But then the base LISP
package is a real pain to explicitly import all the things so commonly used.
I think there is a protection mechanism to prevent its symbols from being
redefined.

But this is a lesson to me -- beware of just blindly USE'ing other packages
without fully realizing what they export.

- DM
From: Kent M Pitman
Subject: Re: Package Question
Date: 
Message-ID: <sfwelmbc988.fsf@shell01.TheWorld.com>
"David McClain" <······@qwest.net> writes:

> ... Actually, I think that points to the danger inherent in just blindly
> USE'ing a package instead of making explicit imports. But then the base LISP
> package is a real pain to explicitly import all the things so commonly used.
> I think there is a protection mechanism to prevent its symbols from being
> redefined.
> 
> But this is a lesson to me -- beware of just blindly USE'ing other packages
> without fully realizing what they export.

Yes.  I think for a novice, overly confining rules like this are good.
Like telling your child that he must always stay on the block of
houses he lives on and never cross the street.  This kind of rule does
not work well in adult life, but adds some security while learning
other things and while waiting to be able to master the skills needed
to safely cross streets.

Certainly style rules evolve that are short and punchy like this and
are worth following until you have deeper knowledge.  But see my
longer post in response to your original query if you want a more
detailed analysis of this problem and why it's good for people to
ultimately want to outgrow this initially-productive style rule.
From: Kent M Pitman
Subject: Re: Package Question
Date: 
Message-ID: <sfwher7c9d4.fsf@shell01.TheWorld.com>
"David McClain" <······@qwest.net> writes:

> Up to now I had the impression that packages were like sharable
> namespaces -- contents protected from outside assault, unless explicit means
> (like IN-PACKAGE) were used to alter their content.
> 
> But I found that by simply using a package inside another client package, I
> could accidentally redefine an imported symbol for my own needs in the
> client package -- and this redefinition actually redefines the used symbol
> back in the original package -- without any warning!!

There are two issues here.  

First, you should NEVER use IN-PACKAGE if you don't intend to be the
implementor of the package you are using.  So there is no bug there.

Second, I have long wished that compilers would issue a style diagnostic
if you tried to define a variable or function from within a package that
did not belong to that package.  That would, of course, get you a lot of
style warnings if you did:

 (in-package "FOO")

 (defun bar:x (x)  ...)

but that's the point.  Probably a mechanism could be created for muffling 
the warning if vendors experimented with this and negotiated with users about
how to make it tolerable.

> Now this seems a bit startling, especially since I received no warning about
> redefining the doit symbol.

As defined now, you have no right to a warning.  What you're saying is the
same as saying you have write access to someone's directory, you've read in
their file and written it out incompatibly, and are surprised you clobbered
their file.  Think of an imported symbol like a hard link in a file system,
if you are a unix user and have ever seen non-symbolic links in action.

> It would seem that barrel-loads of problems could occur downstream, as other
> unsuspecting user packages get their expected behaviors modified by some
> other unknowing client package.

Do not share symbols with people you don't want this to happen for.
Nothing wrong with doing:

 (defun foo (x) (other:foo x))

rather than importing the OTHER package.

> I see in CLHS no mention of what the expected behavior is. In fact, the
> whole issue of package definitions seems still up in the air.

Sure you do.  But CLHS is a specification, not a tutorial.  This is all
implicit in the extensive discussion of how all the various package operations
for inheritance works, what it means for symbols to have the same identity,
how symbol lookup works, etc.  Once you have the same symbol in your hand,
it doesn't matter how it got there.

This is also the reason that CLHS tells you that you must not redefine symbols
in the CL package.  Because to do so would break every other use in the system.
You should apply for yourself the same kinds of rules as are outlined in 
11.1.2.1.1 for *all* packages that you use or  until you're more familiar 
with symbol sharing.

> Is this particular situation implementation dependent?

Absolutely not.

> Or is it the expected behavior?

Absolutely.  It is at the heart of what it traditionally meant to be
"object-oriented" until the term was recently (last decade or two) co-opted
by people who decided to make object-oriented be a design methodology.  The
original meaning of object-oriented really focused on object identity--that
the language and its data were about the identity of things.  Packages allow
you to select which identity the symbol FOO has, but once you have the object
with that identity, there is no trace in the object itself of how you got
to that object.  Just as you can't tell whether the list (1 2) was originally
typed with one space, as (1 2) or three like (1   3) or perhaps with 
intervening comments like (1 ;foo
2 ;bar
) because no trace of its input format is relevant, so too, you can't tell
once you have the symbol in hand whether you wrote FOO:BAR or just BAR or what.
Programs might have constructed the symbol and there might never have been
a source form.  Only the OBJECT matters, and that's what makes it OBJECT 
oriented.  (Sorry, I'm not really yelling, just trying to make the emphasis 
on the right words in flat ASCII.)

> And if so, shouldn't some kind of warning be issued? 

There are some reasons why it might be useful, as I mentioned above, 
but they would be heuristic in any case.  There is ome reason to believe that
compilers could do better than they're doing now, but in the sense of 
"shouldn't the compiler *know* what's going on" the answer is a definite no.
The compiler can't "have to know" because to guarantee its ability to know
is to require information that might in some cases never have been there,
and that in any case would be counter to what is at least necessary and
sometimes even desirable.

To put this in a way that might sound less negative, let me retell a story
about a professor I really liked in school, the late Bill Martin, who taught
a computational linguistics class I took.  He said it this way:  the purpose
of language is not to say the things that are obvious, but to say the things
that are not.  If all we ever wanted to say were the simple things, there 
would be no syntax.  We would simply say "cheese, mouse, eat" and everyone 
would know what was up.  Language syntax exists NOT for the purpose then 
of saying "The mouse ate the cheese" but for saying "The cheese ate the 
mouse".  It is in order that we be able to be surprised that we give ourselves
the ability to construct things beyond the obvious.

So when you encounter thing that surprise you, please do not always get 
out your gun and shoot at them just because people in other language-design
villages find them good sport.  Sometimes they are there for a reason.

The world is FILLED with languages that warn you about everything that seems
even a little out of the ordinary, and one reason we always say that Lisp is
a language about doing what you've been told is impossible is not that we are
miracle workers who can do the literally impossible, but rather that other
languages are quick to label as impossible that which is not impossible.  They
so limit their world view by making one fear certain things that things start
to seem impossible that are not.

In the US, it's nearly impossible to raise a kid any more without a HUGE amount
of income because one can't do things you can still, I think, do in some other
countries like "leave the kid alone for five minutes while you have to be 
away".  I'm sure if the kid dies, you'd be criminally responsible here.
In other countries, people would say "it's too bad the kid died".  You might
look at that and say "of course we should protect our children" but you also
have to look at the infinite expenditure of resources that goes into making
sure there is absolutely no chance that any risk will ever befall a child. 
The cost of insuring that steals other resources from raising children, and is
not zero cost.  It also means you raise kids to think someone will always
protect them instead of raising kids to look out for themselves.  So it's
very double-edged.  

And languages are just like that. Many other languages protect you from what
you might write, and you're talking about an area of CL where it doesn't 
protect you.  

There are places CL does protect you that it might not.  For example, it warns
you about unused lambda variables, even though it's useful sometimes to ignore
them.  It's common place in the functional programming community to write
functions like (lambda (x y) x) and its an annoyance to them to be warned
about this bug.  We had to make an engineering choice in CL of whether to
support that style (quietly compiling that which might be a bug or might be
a useful style).  We decided it doesn't happen often enough that we didn't
want to warn, but we created the IGNORE and IGNORABLE declarations to let
you do that if you wanted.  (lambda (x y) (declare (ignore y)) x).
But by doing so, we not only observe statistics, we create them.  It makes it
less likely that people will use this style.  I don't happen to mind that,
but others might.  There is no way to win totally.  Each decision favors some
group.  The same is true of the symbol identity thing.

> How is a client package ever to know that it might be redefining
> some exported symbol?

Well, good implementations will tell you when you're redefining a function
in a file that it wasn't originally defined in.  That's an optional diagnostic
but it's practiced by a number of compilers and works safely.  But this has
nothing to do with packages.  The same problem could come up and be just as
much a pitfall in one package extending over several files.  That's why
looking for redefinition is better than looking for symbol clashes.

But in the end, you are really asking a question analogous to a carpenter
saying:  "Some of these tools, like the ones that cut things, seem to have
sharp edges.  How am I to know when I cut a piece of wood that I'm not cutting
the wrong piece of wood and making a mess of things?"  I don't know how
carpenters solve this in general, but I bet "good compiler diagnostics" 
are not the answer.  Sometimes you just have to do good bookkeeping in your
head and not make a mistake, I think.  The only alternative would be to limit
the set of tasks to those you could mechanically recognize and warn about,
but then Lisp would no longer be useful for that of problems that its 
linguistic power was up to but its bookkeeping was not up to.

I hope this helps.
From: Duane Rettig
Subject: Re: Package Question
Date: 
Message-ID: <4k7w3c54k.fsf@beta.franz.com>
[Since David McClain is a customer of ours, I would normally have sent him
email directly telling him of features in Allegro CL, instead of posting
here.  But since he uses other lisps also, and since the question both he
and Kent ask are general and the feature in Allegro CL probably not widely
known, I thought I'd respond anyway]

Kent M Pitman <······@world.std.com> writes:

> "David McClain" <······@qwest.net> writes:

> > [ ... ]
> > But I found that by simply using a package inside another client package, I
> > could accidentally redefine an imported symbol for my own needs in the
> > client package -- and this redefinition actually redefines the used symbol
> > back in the original package -- without any warning!!

> [ ... ]
> Second, I have long wished that compilers would issue a style diagnostic
> if you tried to define a variable or function from within a package that
> did not belong to that package.  That would, of course, get you a lot of
> style warnings if you did:
> 
>  (in-package "FOO")
> 
>  (defun bar:x (x)  ...)
> 
> but that's the point.  Probably a mechanism could be created for muffling 
> the warning if vendors experimented with this and negotiated with users about
> how to make it tolerable.

We have done just this over the years.  It has been a hard problem and
several factors have been high in the minds of the implementors that
did the work:

 - The default behavior must conform to strict ANSI CL.
 - There must not be too many warnings
 - When the features are used, there must not be too few warnings.
 - There must be reasonable circumvention of these locks, both on
   individual defintions and on whole packages and situations.

Also, instead of warnings, which might be ignored during long compilations
when the packages are "locked", we make the conditions errors.  But a
non-continuable error is too harsh, so we allow a user to control the
thwarting of the locking on an individual basis.  There is also a way
to circumvent the locking mechanism programmatically, in case there is
no way to intervene manually.

There are a number of features that we implemented which are described here:

http://www.franz.com/support/documentation/6.1/doc/packages.htm#package-locking-1

The two I concentrate on here are the package-definition-lock, which
causes continuable errors when a definition is made while not "in"
the package homing the symbol being defined, and the implementation-package,
which describes those packages for which the home package will not complain.

The example below is partly taken from the documentation described in the above
section, and partly from David's example.  Three packages are defined, foo, bar,
and bas.  The foo package exports doit, which bas then imports.  Also, foo
has as implementation-packages itself and bar, which means that symbols in
foo will not be locked from definition while in package bar (or, of course, foo).
Note in the example run below, package-definition-locks are set for all three
packages, so that other than the exceptions, each will complain about
definitions on symbols homed within them while in other packages.  Note also
that I opted for the default restart in each case, which forces the definition
anyway.

Note also in the example that the error message includes the string "is
a violation for portable programs".  This concept was originated in CL by
making it illegal to define any functions on symbols in the common-lisp
package (the concept is that if more than one user defines the symbol in
different ways, the final definition is not predictable, and one of the
programs will break).  The same concept applies to any package that might be
defined by a user, and it is why we provide the same mechanism for
user-defined packages as we do for common-lisp and other packages
that we define.

CL-USER(1): (defpackage :foo
              #+allegro (:implementation-packages "FOO" "BAR")
              (:export #:doit))
#<The FOO package>
CL-USER(2): (defpackage :bar)
#<The BAR package>
CL-USER(3): (defpackage :bas (:use "FOO" "COMMON-LISP") (:import-from "FOO" foo::doit))
#<The BAS package>
CL-USER(4): (setf (package-definition-lock (find-package :foo)) t)
T
CL-USER(5): (setf (package-definition-lock (find-package :bar)) t)
T
CL-USER(6): (setf (package-definition-lock (find-package :bas)) t)
T
CL-USER(7): (in-package :bar)
#<The BAR package>
BAR(8): (defun foo::mysym (a b) (+ a b))
FOO::MYSYM
BAR(9): (in-package :foo)
#<The FOO package>
FOO(10): (defun bar::my-other-sym (c) (sqrt c))
Error: Attempt to make a FUNCTION definition for the name
       BAR::MY-OTHER-SYM.  This name is in the BAR package and defining
       it is a violation for portable programs.  The package BAR has
       EXCL:PACKAGE-DEFINITION-LOCK set, which causes the system to
       signal this violation.
  [condition type: PACKAGE-LOCKED-ERROR]

Restart actions (select using :continue):
 0: Set the FUNCTION definition of the name BAR::MY-OTHER-SYM anyway.
 1: Return to Top Level (an "abort" restart).
 2: Abort entirely from this process.
[1c] FOO(11): :cont
BAR::MY-OTHER-SYM
FOO(12): (defun doit () 15)
DOIT
FOO(13): (in-package :bas)
#<The BAS package>
BAS(14): (describe 'doit)
DOIT is a SYMBOL.
  It is unbound.
  It is EXTERNAL in the FOO package and accessible in the BAS package.
  Its function binding is #<Interpreted Function DOIT>
    The function takes arguments ()
BAS(15): (defun doit () 16)
Error: Attempt to make a FUNCTION definition for the name DOIT.  This
       name is in the FOO package and redefining it is a violation for
       portable programs.  Replacing the current definition of
       #<Interpreted Function DOIT> may be dangerous.  The package FOO
       has EXCL:PACKAGE-DEFINITION-LOCK set, which causes the system to
       signal this violation.
  [condition type: PACKAGE-LOCKED-ERROR]

Restart actions (select using :continue):
 0: Set the FUNCTION definition of the name DOIT anyway.
 1: Return to Top Level (an "abort" restart).
 2: Abort entirely from this process.
[1c] BAS(16): :cont
DOIT
BAS(17): (doit)
16
BAS(18): 

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: David McClain
Subject: Re: Package Question
Date: 
Message-ID: <Xp9P7.152$Ui5.260285@news.uswest.net>
"Kent M Pitman" <······@world.std.com> wrote

> As defined now, you have no right to a warning.  What you're saying is the
> same as saying you have write access to someone's directory, you've read
in

I went back to CLHS in detail last night after discovering this situation,
and indeed, it conjured up concepts from long ago -- and it does sound very
much like having write access to someone else's directory. I now get a
picture that indicates one grand namespace containing symbols - only one
symbol ever exists by any given name.

But that can't be correct either... how about the keyword package. Somehow,
I frequently manage to construct symbols with meanings that would otherwise
clash with some keyword symbols. So perhaps the keyword package is treated
specially and it isn't a package on the same footing as other packages?

I have long said that to understand a language you have to implement a
compiler for it. I haven't done so for CL, and so my ignorance is showing
through... Had I implemented a CL, then I might have a deeper understanding
of the subtle issues involved. But that is asking an awful lot of the
users... to have them implement a language before they start using it.

>
> > It would seem that barrel-loads of problems could occur downstream, as
other
> > unsuspecting user packages get their expected behaviors modified by some
> > other unknowing client package.
>
> Do not share symbols with people you don't want this to happen for.
> Nothing wrong with doing:
>
>  (defun foo (x) (other:foo x))
>
> rather than importing the OTHER package.

That would be fine -- if it were known in advance that foo were owned by
another package. But when I write code I have no control on the behavior of
future programmers. Now that I realize the situation, I can take the time to
check ownership of symbols -- but how many of you actually do that when you
program?

I would like my application to continue to operate correctly, despite
whatever actions an unrelated sibling package might be taking in the future.
I see now that CL wasn't written with this in mind. So either I export
symbols I deem worthy of use by other packages, or I keep them all local or
imported to my package. I can't control the future and whether or not some
untrustworthy package decides to utilize what I have provided.

But this very situation makes me wonder about several issues:

1. Suppose a package becomes popular to use in other client packages, then
one day, it being loaded into the system ahead of these clients decides to
add another exported symbol of its own new making. But now that could break
all of those clients because they might also have defined that symbol for
themselves. They might break because that new symbol is now used inside the
earlier definitions, and when they redefine it, would cause the old exported
symbols to malfunction.

I see now that they would have had to come to agreement on the definition of
that symbol between themselves, but the old provider package knew nothing of
that when it was originally written. And there is no way for the package
maintainer to know that this package is popular on the other side of the
world...

2. Sibling applications - that run concurrently and know nothing of each
other, could inadvertently step on each other by defining actions named the
same as chosen in the other package.

-------------------
All the more surprising to me... is that for 15 years or so, I have been
successfully using CL without having run into this particular situation...
How is it that I was able to dance in a mine field without ever having
tripped one of them? There is something about CL, in its present form, that
seems to make this possibility a rarity. What is that "thing" about CL?

Spoken language is so fraught with ambiguity. I see now that "shadowing" is
a term that means something subtly different than what I originally thought.
We bring all of our world view with us when we interpret what is said. You
can say shadowing - and it conjures up in my mind something a little
different that what you really meant. Had I been part of the early history
of CL, I would have understood what you wanted me to understand. But I had a
different history and I brought that to the table when I read the new rules.

Here is one area where formalism, through language definition equations,
could help convey the exact meaning intended. But I have never seen such
formalism applied to CL. I see plenty of carefully worded legal documents
describing the situation -- more like the fine print in an insurance policy.
But that still leaves ambiguity of the spoken language.

I see nothing wrong with the freedoms inherent in CL. But having much
freedom means that I need to be aware of the pitfalls of certain actions.
When you want to get a license to fly, you have to put in many hours of
training before you are permitted to go it alone. You don't just buy the
keys to an airplane and start flying. Those hours spent are to help you
understand the pitfalls of various actions in the freedom of 3-D travel here
on Earth.

I am not saying we need similar training programs in CL (maybe we do?) but I
am saying that we need to help future users understand the consequences of
their actions. A set of equations describing the actions of the language
would help to convey this information, without subtly assuming a shared
history and mindset regarding the language.

I am not arguing for changes in the language, nor am I shooting it down. I
think adding warnings, as you indicated in your response, could well
overwhelm a user with useless information most of the time. Then such
warnings would gradually become ignored and fail to have the intended impact
when they were really necessary. But how is a compiler to know when a
warning is or is not important...

I have a strong interest in making human to computer communication more
robust and easier for us as humans. There is a huge impedance mismatch
between us non-perfect mortals, and the rigid perfectionism required by
computers. I don't have any definite answers to the problem yet, and I am
still collecting information on what works and what doesn't work.

- DM
From: Barry Margolin
Subject: Re: Package Question
Date: 
Message-ID: <2D9P7.17$te5.1291@burlma1-snr2>
In article <····················@news.uswest.net>,
David McClain <······@qwest.net> wrote:
>
>"Kent M Pitman" <······@world.std.com> wrote
>
>> As defined now, you have no right to a warning.  What you're saying is the
>> same as saying you have write access to someone's directory, you've read
>in
>
>I went back to CLHS in detail last night after discovering this situation,
>and indeed, it conjured up concepts from long ago -- and it does sound very
>much like having write access to someone else's directory. I now get a
>picture that indicates one grand namespace containing symbols - only one
>symbol ever exists by any given name.
>
>But that can't be correct either... how about the keyword package. Somehow,
>I frequently manage to construct symbols with meanings that would otherwise
>clash with some keyword symbols. So perhaps the keyword package is treated
>specially and it isn't a package on the same footing as other packages?

Programmers don't usually assign function bindings to names in the keyword
package, and the system automatically assigns variable bindings to them
(they're automatically bound to themselves).

So what kind of conflict are you anticipating that you're not getting?
Keywords are usually used just for their identity.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: David McClain
Subject: Re: Package Question
Date: 
Message-ID: <NU9P7.157$Ui5.276227@news.uswest.net>
"Barry Margolin" <······@genuity.net> wrote

> Programmers don't usually assign function bindings to names in the keyword
> package, and the system automatically assigns variable bindings to them
> (they're automatically bound to themselves).
>

Yes, I understood that aspect of CL. And I appreciate that assigning a value
and assigning a function value are really two separate issues. The question
is, why don't I see function bindings on these keyword symbols if I happen
to use a like-named symbol in one of my packages?

Since redefining a function binding on some imported symbol clobbers the
prior function binding, why doesn't this happen with keyword symbols too? It
must be that the keyword symbols are treated specially, and they must exist
in duplicate with respect to like named symbols from other packages. Other
packages, however, share like-named symbol instances.

- DM
From: Thomas F. Burdick
Subject: Re: Package Question
Date: 
Message-ID: <xcv3d2qbs46.fsf@apocalypse.OCF.Berkeley.EDU>
"David McClain" <······@qwest.net> writes:

> "Barry Margolin" <······@genuity.net> wrote
> 
> > Programmers don't usually assign function bindings to names in the keyword
> > package, and the system automatically assigns variable bindings to them
> > (they're automatically bound to themselves).
> >
> 
> Yes, I understood that aspect of CL. And I appreciate that assigning a value
> and assigning a function value are really two separate issues. The question
> is, why don't I see function bindings on these keyword symbols if I happen
> to use a like-named symbol in one of my packages?
> 
> Since redefining a function binding on some imported symbol clobbers the
> prior function binding, why doesn't this happen with keyword symbols too? It
> must be that the keyword symbols are treated specially, and they must exist
> in duplicate with respect to like named symbols from other packages. Other
> packages, however, share like-named symbol instances.

A symbol has a name, but that's just important for humans.  It is a
first-class object, which may or may not live in a package.  Symbols
in different packages, with the same name, are different objects.  Eg:

  * (defpackage "CLL-EXAMPLE" (:use) (:export "FOO")) ;[*]
  #<The CLL-EXAMPLE package, 1/8 internal, 1/2 external>
  * (in-package "CLL-EXAMPLE")
  #<The CLL-EXAMPLE package, 1/8 internal, 1/2 external>
  * 'foo
  FOO
  * (cl:describe 'foo)
  FOO is an internal symbol in the CLL-EXAMPLE package.
  * (cl:in-package "USER")
  #<The COMMON-LISP-USER package, 12/21 internal, 0/9 external>
  * 'foo
  FOO
  * (describe 'foo)
  FOO is an internal symbol in the COMMON-LISP-USER package.
  * (eq 'user::foo 'cll-example:foo)
  NIL
  * (defpackage "CLL-EXAMPLE2" (:use "CLL-EXAMPLE"))
  #<The CLL-EXAMPLE2 package, 0/9 internal, 0/2 external>
  * (in-package "CLL-EXAMPLE2")
  #<The CLL-EXAMPLE2 package, 0/9 internal, 0/2 external>
  * 'foo
  FOO
  * (cl:describe 'foo)
  FOO is an external symbol in the CLL-EXAMPLE package.
  * (cl:eq 'foo 'user::foo)
  COMMON-LISP:NIL
  * (cl:in-package "USER")
  #<The COMMON-LISP-USER package, 2/9 internal, 0/9 external>
  * (defpackage "CLL-EXAMPLE3" (:use) (:export "FOO"))
  #<The CLL-EXAMPLE3 package, 0/8 internal, 1/2 external>
  * (eq 'cll-example:foo 'cll-example3:foo)
  NIL
  * (defpackage "CLL-EXAMPLE4" (:use "CLL-EXAMPLE" "CLL-EXAMPLE3"))
  
  
  Error in function USE-PACKAGE:
     Use'ing package CLL-EXAMPLE results in name conflicts for these symbols:
  (CLL-EXAMPLE3:FOO)
  
  Restarts:
    0: [CONTINUE] Unintern the conflicting symbols in the CLL-EXAMPLE4 package.
    1: [ABORT   ] Return to Top-Level.
  
  Debug  (type H for help)
  
  (USE-PACKAGE
   (#<The CLL-EXAMPLE package, 1/8 internal, 1/2 external>
    #<The CLL-EXAMPLE3 package, 0/8 internal, 1/2 external>)
   #<The CLL-EXAMPLE4 package, 0/9 internal, 0/2 external>)
  0] 

Hopefully that helps clear things up?

[*] I was going to call this package FOO, but then I noticed that I'd
been developing in the FOO package.  Oops.  So, I'm glad I typed up
this example :-)

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Barry Margolin
Subject: Re: Package Question
Date: 
Message-ID: <FBaP7.21$te5.1496@burlma1-snr2>
In article <····················@news.uswest.net>,
David McClain <······@qwest.net> wrote:
>Yes, I understood that aspect of CL. And I appreciate that assigning a value
>and assigning a function value are really two separate issues. The question
>is, why don't I see function bindings on these keyword symbols if I happen
>to use a like-named symbol in one of my packages?

Because each package is an independent namespace.  The symbols P1::FOO,
P2::FOO, and :FOO are all different symbols (unless one of the packages
uses the other, or symbols are imported), and changes made to one have no
effect on the others.  As long as you don't (use-package "KEYWORD") you
should never have a problem if one of your symbols happens to have the same
name as a keyword.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: David McClain
Subject: Re: Package Question
Date: 
Message-ID: <oLaP7.169$Ui5.308193@news.uswest.net>
Yes, I am beginning to grasp what is going on... It does in fact appear that
each package is a separate namespace - for non-exported symbols only. Once a
symbol is exported it seems to become part of a larger system-wide namespace
that is susceptible to casual redefinition -- unless protected by a scheme
like that described by Duane.

- DM
From: Duane Rettig
Subject: Re: Package Question
Date: 
Message-ID: <4g06qd6pp.fsf@beta.franz.com>
"David McClain" <······@qwest.net> writes:

> Yes, I am beginning to grasp what is going on... It does in fact appear that
> each package is a separate namespace - for non-exported symbols only. Once a
> symbol is exported it seems to become part of a larger system-wide namespace

Well, sort of.  As soon as a symbol is exported, it becomes available for
other packages to import, either by importing it explicitly, or implicitly
by use-package.  Note however that CL's philosophy is one of openness; it
does not disallow reference of any symbol in its system regardless of the
package (unlike other languages which actually hide some classes of symbols).
Thus, foo::bar can _always_ be accessed as foo::bar, whether in the foo package
or not.  But the double-colon is an immediate visual red flag that something
strange is happening, and to be careful.

> that is susceptible to casual redefinition -- unless protected by a scheme
> like that described by Duane.

"casual" is the keyword here.  Redefinition of _any_ symbol is possible
(unless a locking scheme like I described is in effect), but defining an
internal symbol in a different package is intentionally clumsy so that
the unsuspecting programmer won't generally run into it accidentally.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Marco Antoniotti
Subject: Re: Package Question
Date: 
Message-ID: <y6c3d2qwts6.fsf@octagon.mrl.nyu.edu>
"David McClain" <······@qwest.net> writes:

> Yes, I am beginning to grasp what is going on... It does in fact appear that
> each package is a separate namespace - for non-exported symbols only. Once a
> symbol is exported it seems to become part of a larger system-wide namespace
> that is susceptible to casual redefinition -- unless protected by a scheme
> like that described by Duane.

Yes.  You have to be careful.

Note that everything is subject to "casual redefinition"

In file 1

(defun foo (x) x)

In file 2

(defun foo (x) (* 2 x))

Or even in the same file.  There is no package issue here.  This is
just the nature of the beast.

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Kent M Pitman
Subject: Re: Package Question
Date: 
Message-ID: <sfwwv027b9b.fsf@shell01.TheWorld.com>
"David McClain" <······@qwest.net> writes:

> Yes, I am beginning to grasp what is going on... It does in fact appear that
> each package is a separate namespace - for non-exported symbols only. Once a
> symbol is exported it seems to become part of a larger system-wide namespace
> that is susceptible to casual redefinition -- unless protected by a scheme
> like that described by Duane.

You're confused in your explanation.

Packages are not subject to redefinition or not.

Even from another package, you can do

 (defun foo::bar (x) ...)

and redefine an internal symbol of another package with ill results.
The issue of redefinition is not package-related.  Packages are just
mechanisms that help you gain access to objects.  The objects, once
accessed, are all treated uniformly.  No statement talks about
packages being susceptible or non-susceptible to redefinition is going
to be right.  Symbols are what get defined or redefined.  Packages
control the naming conventions for getting to symbols, but no package
denies you access to any other if you're willing to do the right
notation.  And no redefinition is ever safe unless you've studied the
code and decided you want the redefinition in the case of all uses,
independent of what notation was used to gain access in each of those
uses.  Packages offer you the ability to control the relative ease
with which you have access to symbols, but that's pretty much all.
From: David McClain
Subject: Re: Package Question
Date: 
Message-ID: <sAaP7.165$Ui5.302195@news.uswest.net>
Now, after a few minutes experimenting, I see that I had some confusion,
even now, about the management of CL symbols. Non-exported symbols are safe
against redifintion in other packages.

That would imply that using syntax p::s is actually a preferable way to use
foreign package symbols, and let the foreign package actually keep them as
non-exported.

Up to now, I had thought that accessing package internal symbols of another
package was a sure way to violate portability. If the package hadn't
exported a symbol, then it might have had good reasons for wanting to keep
things private.

It is just the exported symbols that are at risk of redefinition. There
appears to be no subdivision in the package system between those
non-exported symbols intended to be kept private, and those non-exported
symbols intended for client access.

So I guess my main misunderstandings had to do with the behavior of the
exported package interface. It is not exactly the same thing as an
advertised interface definition in other languages -- listing features that
are accessible to the user, but which are immutable against user
redefinition.

You know, the older I get, the more often I rediscover things which I
already knew at an earlier time....

- DM
From: Barry Margolin
Subject: Re: Package Question
Date: 
Message-ID: <DHaP7.22$te5.1499@burlma1-snr2>
In article <····················@news.uswest.net>,
David McClain <······@qwest.net> wrote:
>Now, after a few minutes experimenting, I see that I had some confusion,
>even now, about the management of CL symbols. Non-exported symbols are safe
>against redifintion in other packages.
>
>That would imply that using syntax p::s is actually a preferable way to use
>foreign package symbols, and let the foreign package actually keep them as
>non-exported.

If a symbol isn't exported, you're typically not expected to use it at all
from outside the package.  They're usually not documented, and subject to
removal in future releases.

>Up to now, I had thought that accessing package internal symbols of another
>package was a sure way to violate portability. If the package hadn't
>exported a symbol, then it might have had good reasons for wanting to keep
>things private.

This is usually a good assumption.

>It is just the exported symbols that are at risk of redefinition. There
>appears to be no subdivision in the package system between those
>non-exported symbols intended to be kept private, and those non-exported
>symbols intended for client access.

Being internal or external has little to do with their risk of
redefinition.  You could do:

(defun p::s ...)

and redefine an internal symbol.

The main reason why you're running into redefinition issues is because you
insist on using USE-PACKAGE.  Instead, you should access symbols from the
other package using P:S syntax.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: David McClain
Subject: Re: Package Question
Date: 
Message-ID: <gOaP7.173$Ui5.309970@news.uswest.net>
"Barry Margolin" <······@genuity.net> wrote
>
> Being internal or external has little to do with their risk of
> redefinition.  You could do:
>
> (defun p::s ...)
>
> and redefine an internal symbol.
>

I had never seen anyone do such a thing... But its syntax cries out that
something peculiar is afoot.

> The main reason why you're running into redefinition issues is because you
> insist on using USE-PACKAGE.  Instead, you should access symbols from the
> other package using P:S syntax.
>

Yes, indeed... Very good point. But that still leaves known working systems
susceptible to ignorant programmers like me in the future...  Ah well...

- DM
From: Thomas F. Burdick
Subject: Re: Package Question
Date: 
Message-ID: <xcvu1v6abrf.fsf@apocalypse.OCF.Berkeley.EDU>
"David McClain" <······@qwest.net> writes:

> > The main reason why you're running into redefinition issues is because you
> > insist on using USE-PACKAGE.  Instead, you should access symbols from the
> > other package using P:S syntax.
> 
> Yes, indeed... Very good point. But that still leaves known working systems
> susceptible to ignorant programmers like me in the future...  Ah well...

But it would also prevent me from doing something like this:

  (defmacro dynamic-flet (forms &body body)
    "Like FLET, but only affects the global function binding, and does so
     with dynamic, not lexical scope.  This useful for porting elisp code."
    (let ((old-vals (loop for (name) in forms collecting (cons name (gensym))))
          (new-vals (loop for (name) in forms collecting (cons name (gensym)))))
      `(let (,@(loop for (name . sym) in old-vals
                     collecting `(,sym (symbol-function ',name)))
             ,@(loop for (name . fn) in forms
                     for sym = (cdr (assoc name new-vals))
                     collecting `(,sym (lambda ,@fn))))
         (unwind-protect
              (progn
                ,@(loop for (name . sym) in new-vals
                        collecting `(setf (symbol-function ',name) ,sym))
                ,@body)
           ,@(loop for (name . sym) in old-vals
                   collecting `(setf (symbol-function ',name) ,sym))))))

  (defun foo ()
    (dynamic-flet ((other-package:entry-point (x)
                     (if (handle-this-case-p x)
                         (my-entry-point x)
                         (other-package:entry-point x))))
      (yet-another-package:do-something)))   

And personally, I'd rather insist that people are comfortable with the
CL package system before they hack on real applications, than make it
safer for the naive user, but at the cost of power.  Besides, once you
get the hang of it, it's not confusing.  It's just surprisingly
object-oriented at first blush.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Tim Bradshaw
Subject: Re: Package Question
Date: 
Message-ID: <fbc0f5d1.0112050543.746db4d6@posting.google.com>
"David McClain" <······@qwest.net> wrote in message news:<····················@news.uswest.net>...
> Yes, indeed... Very good point. But that still leaves known working systems
> susceptible to ignorant programmers like me in the future...  Ah well...

I think this is partly an issue of documentation and idiocy (I'm *not*
implying you are an idiot.  You or I may do idiotic things (I do, all
the time) but that's a different statement. For the record I don't
think you are.)

If I provide some system to you, then I'd expect to also provide
documentation for it which would say stuff like `the class FOO does
xxx' and `the function BAR does yyy' and `the following functions are
not yet implemented: GRUMBLE, WHIRR'.  If the names in the interface
to my system are exported from the TFBS-WHIRR-SYSTEM package, then I'd
expect that *just* the symbols I've documented are exported and,
further, that you've read the documentation and what it says about
whether you can redefine/add methods to/whatever things, and don't
randomly go around clobbering bits of my system.  Similarly I'd expect
that, if I secretly export some symbol I've failed to document, then
if you clobber this, well that's my problem.

Now, of course, 98% of everything is not documented, so this doesn't
really apply, but I think in the good case it should be reasonably
clear that after you've a (use-package :tfbs-whirr-system) then you've
undertaken not to clobber the symbols I've told you not to (and I've
undertaken not to export stuff I haven't told you about).

--tim
From: Russell Senior
Subject: Re: Package Question
Date: 
Message-ID: <86lmgibmz4.fsf@coulee.tdb.com>
>>>>> "Kent" == Kent M Pitman <······@world.std.com> writes:

Kent> [...]  But CLHS is a specification, not a tutorial.  [...]

I have often wished I knew where to find a tutorial on packages and
also pathnames.  I don't see the subject treated very thoroughly in
the CL literature.  If I am merely blind, I would like to be healed,
if possible.


-- 
Russell Senior         ``The two chiefs turned to each other.        
·······@aracnet.com      Bellison uncorked a flood of horrible       
                         profanity, which, translated meant, `This is
                         extremely unusual.' ''                      
From: Kent M Pitman
Subject: Re: Package Question
Date: 
Message-ID: <sfwu1v67b3o.fsf@shell01.TheWorld.com>
Russell Senior <·······@aracnet.com> writes:

> >>>>> "Kent" == Kent M Pitman <······@world.std.com> writes:
> 
> Kent> [...]  But CLHS is a specification, not a tutorial.  [...]
> 
> I have often wished I knew where to find a tutorial on packages and
> also pathnames.  I don't see the subject treated very thoroughly in
> the CL literature.  If I am merely blind, I would like to be healed,
> if possible.

Yeah, they are mostly obsessed with producing armies of programmers
capable of writing reverse, just in case there's still a language that
doesn't have that capability.  I made a note for my books-in-progress.
I agree this is a good set of topic areas. Thanks!  Sorry I don't have
such info already handy to offer tho...
 --Kent
From: Erik Naggum
Subject: Re: Package Question
Date: 
Message-ID: <3216516931977597@naggum.net>
* Kent M Pitman
| Yeah, they are mostly obsessed with producing armies of programmers
| capable of writing reverse, just in case there's still a language that
| doesn't have that capability.

  Heh.  The often stupid exercises we find in introductions to (Common)
  Lisp may in fact be a _good_ reason for someone who is introduced to the
  langauge this way to avoid (Common) Lisp in the future.  What _do_ they
  tell people but that (Common) Lisp lacks all useful features?  Not only
  does the language impose a whole new way of thinking about things, it has
  a whole new way of doing all the stuff they learned in Algorithms 101.

  Real (Common) Lisp programmers love the language for the fact that they
  do _not_ have to implement everything from scratch.  (If they wanted
  that, they would have chosen Scheme, and, indeed, most of the idiotic
  exercises in introductions to "Lisp" are really for Scheme.)  I think
  this simple fact completely eludes those who write introductory books,
  because it is somehow not considered pedagogically kosher to assume that
  programmers are smart enough to pick up most of the simple things in the
  first lecture (nor to ignore those who do not).

  I do not think it is the parentheses or the prefix syntax that "drive
  people away" at all, but rather the annoying condescension towards new
  programmers in the books they are offered to learn the language from, as
  if they needed to learn how to implement basic algorithms, as if the
  prefix syntax and the parentheses somehow need to be over-focused on in
  an apologetic way.

  The trivial functions they are asked to implement is the kind of stuff
  they should be exposed to so they could _read_ good source code instead
  of having to write little toy versions that are broken.  Also, if they
  read good code for these non-trivial things, they would understand just
  how good they are in practical use, which their own versions of them
  would frankly not be.  Moreover, the real code to implement reverse and
  other useful functions may be vastly more complex than the usual simple
  stuff that people are confronted with, or implement, with real concerns
  about not wasting resources and being very efficient.

  After all, the reason we have a big language is so people can be relieved
  of doing everything with stone-age tools.  To trust that everything is
  implemented well, however, one might need to provide programmers with
  actual source code and a demonstration how to make these things work
  correctly and efficiently.  Franz Inc does this to paying customers, but
  I do not know how other commercial vendors do this.

///
-- 
  The past is not more important than the future, despite what your culture
  has taught you.  Your future observations, conclusions, and beliefs are
  more important to you than those in your past ever will be.  The world is
  changing so fast the balance between the past and the future has shifted.
From: Raymond Toy
Subject: Re: Package Question
Date: 
Message-ID: <4n3d2p4nbz.fsf@rtp.ericsson.se>
>>>>> "Kent" == Kent M Pitman <······@world.std.com> writes:

    Kent> Russell Senior <·······@aracnet.com> writes:
    >> >>>>> "Kent" == Kent M Pitman <······@world.std.com> writes:
    >> 
    Kent> [...]  But CLHS is a specification, not a tutorial.  [...]
    >> 
    >> I have often wished I knew where to find a tutorial on packages and
    >> also pathnames.  I don't see the subject treated very thoroughly in
    >> the CL literature.  If I am merely blind, I would like to be healed,
    >> if possible.

    Kent> Yeah, they are mostly obsessed with producing armies of programmers
    Kent> capable of writing reverse, just in case there's still a language that
    Kent> doesn't have that capability.  I made a note for my books-in-progress.
    Kent> I agree this is a good set of topic areas. Thanks!  Sorry I don't have
    Kent> such info already handy to offer tho...

Add conditions and "proper" use of conditions to that list. :-) 

I always have problems with this because I don't do it often enough to
remember.

Ray
From: Vebjorn Ljosa
Subject: Re: Package Question
Date: 
Message-ID: <cy3d6zommct.fsf@ljosa.com>
* Raymond Toy <···@rtp.ericsson.se>
| * Kent M Pitman <······@world.std.com>
| | * Russell Senior <·······@aracnet.com>
| | | 
| | | I have often wished I knew where to find a tutorial on packages and
| | | also pathnames.  I don't see the subject treated very thoroughly in
| | | the CL literature.  If I am merely blind, I would like to be healed,
| | | if possible.
| | 
| | Yeah, they are mostly obsessed with producing armies of programmers
| | capable of writing reverse, just in case there's still a language that
| | doesn't have that capability.  I made a note for my books-in-progress.
| | I agree this is a good set of topic areas. Thanks!  Sorry I don't have
| | such info already handy to offer tho...
| 
| Add conditions and "proper" use of conditions to that list. :-) 
| 
| I always have problems with this because I don't do it often enough to
| remember.

I learned a lot about conditions from the following paper:

Kent M. Pitman, "Condition handling in the Lisp language family," in
Advances in Exception Handling Techniques, Alexander Romanovsky,
Christophe Dony, J�rgen Lindskov Knudsen, and Anand Tripathi, Eds.,
2001, vol. 2022 of Lecture Notes in Computer Science, pp. 39--59,
Springer.

-- 
Vebjorn Ljosa