From: Erann Gat
Subject: Idiot's guide to packages
Date: 
Message-ID: <gat-2906031521030001@192.168.1.51>
A first draft of "The Complete Idiot's Guide to Common Lisp Packages" is
available at http://www.flownet.com/gat/packages.pdf.  A .doc version is
also available there.  Comments and feedback are welcome, preferably by
email.  I'm interested in getting feedback both from newbies (is it
understandable?) as well as experienced Lispers (is it correct?).

Note: this is a hurriedly-written first draft and almost certainly
contains mistakes.

Erann

From: Nick Levine
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <8732fc48.0306292308.828b2aa@posting.google.com>
Erann,

> A first draft of "The Complete Idiot's Guide to Common Lisp Packages" is
> available at http://www.flownet.com/gat/packages.pdf.  

Thanks for doing this. Would you consider adding it to the Common Lisp
cookbook? The piece it has on packages at present is very short.

http://cl-cookbook.sourceforge.net/

-nick
From: Erann Gat
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <gat-3006030803260001@192.168.1.51>
In article <···························@posting.google.com>,
···@ravenbrook.com (Nick Levine) wrote:

> Erann,
> 
> > A first draft of "The Complete Idiot's Guide to Common Lisp Packages" is
> > available at http://www.flownet.com/gat/packages.pdf.  
> 
> Thanks for doing this. Would you consider adding it to the Common Lisp
> cookbook?

That's the plan, but I want to do at least one round of revisions first.

E.
From: Erann Gat
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <gat-3006031526520001@k-137-79-50-101.jpl.nasa.gov>
In article <····················@192.168.1.51>, ···@jpl.nasa.gov (Erann
Gat) wrote:

> In article <···························@posting.google.com>,
> ···@ravenbrook.com (Nick Levine) wrote:
> 
> > Erann,
> > 
> > > A first draft of "The Complete Idiot's Guide to Common Lisp Packages" is
> > > available at http://www.flownet.com/gat/packages.pdf.  
> > 
> > Thanks for doing this. Would you consider adding it to the Common Lisp
> > cookbook?
> 
> That's the plan, but I want to do at least one round of revisions first.

A revised version of the Idiot's Guide to Packages is now on-line at the
above URL.  The copyright notice grants permission for non-commercial use,
so anyone who wants to add it to the Cookbook is welcome to do so.  (I'm
not on the developer list so I can't do it myself.)

E.
From: Adam Warner
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <pan.2003.06.30.03.11.46.152924@consulting.net.nz>
Hi Erann Gat,

> A first draft of "The Complete Idiot's Guide to Common Lisp Packages" is
> available at http://www.flownet.com/gat/packages.pdf.  A .doc version is
> also available there.  Comments and feedback are welcome, preferably by
> email.  I'm interested in getting feedback both from newbies (is it
> understandable?) as well as experienced Lispers (is it correct?).

[I've replied to the newsgroup and to your email address]

> Note: this is a hurriedly-written first draft and almost certainly
> contains mistakes.

I found it helpful thanks Erann. Note that it's also a "Highly Technical
Guide to Common Lisp Symbols." You made my brain hurt learning about
GENTEMP, SET and MAKE-SYMBOL for the first time!

I'd appreciate a discussion about whether one can unshadow a shadowed
symbol (say I have shadowed some core Common Lisp functionality and I want
to restore the original functionality). I think this could make your point
about packages being about symbols and not the function associated with that
symbol. Does shadowing detach the originally associated function so it
cannot be recovered?

Thanks,
Adam
From: Erann Gat
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <gat-2906032202310001@192.168.1.51>
In article <······························@consulting.net.nz>, Adam Warner
<······@consulting.net.nz> wrote:

> Hi Erann Gat,
> 
> > A first draft of "The Complete Idiot's Guide to Common Lisp Packages" is
> > available at http://www.flownet.com/gat/packages.pdf.  A .doc version is
> > also available there.  Comments and feedback are welcome, preferably by
> > email.  I'm interested in getting feedback both from newbies (is it
> > understandable?) as well as experienced Lispers (is it correct?).
> 
> [I've replied to the newsgroup and to your email address]

Thanks for the feedback.

> I found it helpful thanks Erann. Note that it's also a "Highly Technical
> Guide to Common Lisp Symbols." You made my brain hurt learning about
> GENTEMP, SET and MAKE-SYMBOL for the first time!

Hm, I'm not sure offhand how to make that any less painful.  (And I didn't
even mention GENSYM or symbol macros :-)

> I'd appreciate a discussion about whether one can unshadow a shadowed
> symbol (say I have shadowed some core Common Lisp functionality and I want
> to restore the original functionality).

You "unshadow" a symbol by uninterning it.  I'll add a more complete
explanation of this.  (By the time I got to the shadowing section *my*
head was hurting :-)

> I think this could make your point
> about packages being about symbols and not the function associated with that
> symbol. Does shadowing detach the originally associated function so it
> cannot be recovered?

Shadowing/unshadowing/importing/exporting all do nothing at all to the
functions and values associated with a symbol.  And as long as a symbol is
interned in at least one package you can always access that symbol (and
therefore retrieve and value/function/plist/etc. associated with it) by
using its fully qualified name. (I'll add this to the guide too.)

E.
From: thelifter
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <b295356a.0307011512.1c91fd65@posting.google.com>
Hello,

I have read it and have the following questions:
Please include page numbers in the next release, I'm counting the
pages using the
thumbnails.

On page5:

? (trace make-symbol) NIL 
? 'foobaz 
Calling (MAKE-SYMBOL "FOOBAZ") 
MAKE-SYMBOL returned #:FOOBAZ 
FOOBAZ

On page7:

? (list 'x1 
Calling (MAKE-SYMBOL "'X1") 
MAKE-SYMBOL returned #:\'X1 
'x2 
Calling (MAKE-SYMBOL "'X2") 
MAKE-SYMBOL returned #:\'X2 
'x3 etc...

Question1:
I wonder why in the second case the quote is included in the call to
MAKE-SYMBOL. And why does MAKE-SYMBOL return \' (backslash quote)?


On page 10:

? (in-package bob) 
#<Package "BOB"> 
? 'weird-symbol 
WEIRD-SYMBOL 
? (symbol-package 'weird-symbol) 
NIL 
? (in-package jane) 
#<Package "JANE"> 
? 'bob::weird-symbol 
#:WEIRD-SYMBOL

Question2:
I wonder why when 'weird-symbol is evaluated in package bob it isn't
printed
with "#:"
since it doesn't have a home-package anymore.


Thanks for answers...
From: Erann Gat
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <gat-0107031734000001@192.168.1.51>
In article <····························@posting.google.com>,
·········@gmx.net (thelifter) wrote:

> Hello,
> 
> I have read it and have the following questions:
> Please include page numbers in the next release, I'm counting the
> pages using the
> thumbnails.
> 
> On page5:
> 
> ? (trace make-symbol) NIL 
> ? 'foobaz 
> Calling (MAKE-SYMBOL "FOOBAZ") 
> MAKE-SYMBOL returned #:FOOBAZ 
> FOOBAZ
> 
> On page7:
> 
> ? (list 'x1 
> Calling (MAKE-SYMBOL "'X1") 
> MAKE-SYMBOL returned #:\'X1 
> 'x2 
> Calling (MAKE-SYMBOL "'X2") 
> MAKE-SYMBOL returned #:\'X2 
> 'x3 etc...
> 
> Question1:
> I wonder why in the second case the quote is included in the call to
> MAKE-SYMBOL. And why does MAKE-SYMBOL return \' (backslash quote)?
> 

That's a very good question.  The answer is that I don't know.  It
shouldn't be that way.  The single-quotes shouldn't be there.  I suspect
it has something to do with some weirdness resulting from
cutting-and-pasting back and forth between MCL and Word, and the fact that
Word had smart-quotes on, but I can't come up with a plausible sequence of
events that would produce this result.  I'll re-run this and make sure the
corret text gets into a revised version.

Thanks for catching this.

> 
> On page 10:
> 
> ? (in-package bob) 
> #<Package "BOB"> 
> ? 'weird-symbol 
> WEIRD-SYMBOL 
> ? (symbol-package 'weird-symbol) 
> NIL 
> ? (in-package jane) 
> #<Package "JANE"> 
> ? 'bob::weird-symbol 
> #:WEIRD-SYMBOL
> 
> Question2:
> I wonder why when 'weird-symbol is evaluated in package bob it isn't
> printed
> with "#:"
> since it doesn't have a home-package anymore.
> 

Because the WEIRD-SYMBOL is interned in the BOB package.  The rule for
printing symbols is: if the symbol is interned in the current package,
just print its name.  If it isn't interned in the current package, then
print it with a prefix, using the home package as that prefix.

What makes WEIRD-SYMBOL weird is that it is has no home package (so its
symbol-package is nil) despite the fact that it is interned in the BOB
package.

Did that help?  (This is a rather confusing topic.)

E.
From: thelifter
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <b295356a.0307031728.19d789dc@posting.google.com>
···@jpl.nasa.gov (Erann Gat) wrote in message news:<····················@192.168.1.51>...
> Because the WEIRD-SYMBOL is interned in the BOB package.  The rule for
> printing symbols is: if the symbol is interned in the current package,
> just print its name.  If it isn't interned in the current package, then
> print it with a prefix, using the home package as that prefix.
> 
> What makes WEIRD-SYMBOL weird is that it is has no home package (so its
> symbol-package is nil) despite the fact that it is interned in the BOB
> package.
> 
> Did that help?  (This is a rather confusing topic.)
> 

Yes it helped, I think it would be good to add this explanation to the
original, document, others might have the same question. I think the
reason for the confusion is:

#:   ==>  Symbol has no home package
But:
#:  !<==  Symbol has no home package

I'm reading version 1.2 now and found the following:

Missing word here(page 12):

The shadowing symbols list is a list of symbols that shadow or
override any
symbols #########  would normally become visible in that package as a
result of
        ^^^^^^^^^
calling USE-PACKAGE.


New questions:

page 12(again):

? (symbol-package 'slot1) 
#<Package "JANE"> 
? (unintern 'slot1) 
NIL 
? (symbol-package 'slot1) 
#<Package "JANE"> 
?

What is the explanation for this behaviour? Obviously it has something
to do
with the way that use-package alters the reader, but the details
escape me.

Last page:
to solve the exercise to the reader I need to know what the #.# does
to it
in (funcall #.#'foo)!

Pun intended :)
From: Kalle Olavi Niemitalo
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <87r8563aac.fsf@Astalo.kon.iki.fi>
·········@gmx.net (thelifter) writes:

> ? (symbol-package 'slot1) 
> #<Package "JANE"> 
> ? (unintern 'slot1) 
> NIL 
> ? (symbol-package 'slot1) 
> #<Package "JANE"> 
> ?
>
> What is the explanation for this behaviour?

When the Lisp reads "(symbol-package 'slot1)", it looks for a
symbol named "SLOT1" accessible in the current package.  It
doesn't find one, because the symbol that used to be there has
been uninterned.  Then, the Lisp interns a _new_ symbol with that
name.  This new symbol gets the current package as its home
package.  So the SLOT1 in the first form and the SLOT1 in the
third form are different symbols.

[1]> (defpackage "JANE" (:use "CL"))
#<PACKAGE JANE>
[2]> (in-package "JANE")
#<PACKAGE JANE>
JANE[3]> (defvar *1* 'slot1)    ; interns "SLOT1" in the current package
*1*
JANE[4]> *1*
SLOT1
JANE[5]> (unintern 'slot1)      ; uninterns the symbol
T
JANE[6]> *1*                    ; *1* still refers to the uninterned symbol
#:SLOT1
JANE[7]> (defvar *2* 'slot1)    ; again interns "SLOT1", making a new symbol
*2*
JANE[8]> *2*
SLOT1
JANE[9]> *1*                    ; the old one is still uninterned
#:SLOT1
JANE[10]> (eq *1* *2*)          ; they are different symbols
NIL
JANE[11]> 

> Obviously it has something to do with the way that use-package
> alters the reader, but the details escape me.

Not really.  You can do the same in the default COMMON-LISP-USER
package, if you choose a symbol that COMMON-LISP-USER does not
inherit from any implementation-specific package.

> Last page:
> to solve the exercise to the reader I need to know what the #.# does
> to it
> in (funcall #.#'foo)!

#. means read-time evaluation.  Lisp reads the next form,
evaluates it right there and then uses the result.  Everything
needed for evaluating the form must be available at read time.
For example, if the form calls a function, then that function
must be defined before the form is read.  This typically requires
the use of EVAL-WHEN, because the file compiler reads too.

#'foo is read as (function foo).
From: thelifter
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <b295356a.0307041127.7c604676@posting.google.com>
Kalle Olavi Niemitalo <···@iki.fi> wrote in message news:<··············@Astalo.kon.iki.fi>...
> ·········@gmx.net (thelifter) writes:
> 
> > ? (symbol-package 'slot1) 
> > #<Package "JANE"> 
> > ? (unintern 'slot1) 
> > NIL 
> > ? (symbol-package 'slot1) 
> > #<Package "JANE"> 
> > ?
> >
> > What is the explanation for this behaviour?
> 
> When the Lisp reads "(symbol-package 'slot1)", it looks for a
> symbol named "SLOT1" accessible in the current package.  It
> doesn't find one, because the symbol that used to be there has
> been uninterned.  Then, the Lisp interns a _new_ symbol with that
> name.  This new symbol gets the current package as its home
> package.  So the SLOT1 in the first form and the SLOT1 in the
> third form are different symbols.

Sorry, I think your explanation is wrong. The problem is, I made only
an uncomplete copy from the original document. In the fragment above
the current package is BOB and not Jane. Here is the complete fragment
for a better understanding of the question:

? (in-package jane) 
#<Package "JANE"> 
? (export '(slot1 slot2 slot3)) 
T 
? (in-package bob) 
#<Package "BOB"> 
? (use-package 'jane) 
T 
? (symbol-package 'slot1) 
#<Package "JANE"> 
? (unintern 'slot1) 
NIL 
? (symbol-package 'slot1) 
#<Package "JANE"> 
?

According to your explanation the last result should be #<Package
"BOB">, but it isn't!

So, how do you explain it?
From: Kalle Olavi Niemitalo
Subject: correction Re: Idiot's guide to packages
Date: 
Message-ID: <87r856dmly.fsf_-_@Astalo.kon.iki.fi>
I am sorry.  My previous explanation was rather wrong.
I was using a text-only system and had not read the PDF yet,
so I did not realize how the packages had been set up.

·········@gmx.net (thelifter) writes:

> page 12(again):
>
> ? (symbol-package 'slot1) 
> #<Package "JANE"> 
> ? (unintern 'slot1) 
> NIL 
> ? (symbol-package 'slot1) 
> #<Package "JANE"> 
> ?
>
> What is the explanation for this behaviour?

(The current package is BOB, which uses package JANE, which
exports SLOT1.)

The catch is that SLOT1 has not been interned in the BOB package.
Using a package does not intern its exported symbols; it merely
makes them "accessible" (the standard uses this term) by
inheritance.  Because of this, UNINTERN has no effect.

If you then do

  (in-package jane)
  (unexport 'slot1)
  (in-package bob)
  (symbol-package 'slot1)

the symbol JANE::SLOT1 will no longer be available in BOB, even
though nothing has been done to it in BOB itself.

When the reader sees slot1, the effect is as if it first looked
for "SLOT1" interned in the current package (BOB) and then went
through all the packages (COMMON-LISP and JANE) used by the
current package and looked for "SLOT1" exported from them.  If
JANE no longer exports SLOT1, then the reader no longer finds the
symbol, so it makes a new one.

In contrast, if you had imported the symbol into BOB with
(import 'jane:slot1), then it would stay imported even after
JANE unexports it.
From: Nick Levine
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <8732fc48.0307030738.56b1d49c@posting.google.com>
Re draft version 1.2 of "The Complete Idiot's Guide to Common Lisp
Packages", available at http://www.flownet.com/gat/packages.pdf:

Thanks again for writing this, and for letting the cookbook link to
it. Some comments:

1) gentemp and set are deprecated from the language and shouldn't be
used in tutorail material.

2) I don't think you explicitly explained the #: reader macro anywhere
3) Double colons aren't just harder to type, they stick out like a
sore thumb (or: they're easy to search for) when you're enforcing a
"no unexported symbols" house rule. Generally such rules are Good
Things.

4) You mentioned using keywords or strings in defpackage forms.
Another trick I've seen is to use uninterned symbols. Tufte would
complain there's too much ink on the page, but in terms of CL usage
it's not flawed. Also, note that the same issue applies to in-package
forms, as they're typically poor places to accidentally intern
anything.

5) You mention keywords once or twice, in passing. They probably need
better than that.

- nick
From: thelifter
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <b295356a.0307031602.6eb8b9be@posting.google.com>
Excuse me for mentioning Java here, but IMHO it has created a simple
and powerfull way of handling packages. The idea of associating the
package name
with the directory structure was a good design decision.
For those who don't know Java a short explanation:

In Java everything has to be in a package. The first line of a Java
source file
names the package like:

Package editor.textfiles;

public class CsvFile{...

This means that your source File has to be in a path that ends with

.../editor/textfiles/CsvFile.java

To use another package in your program, you use the import statement
at the beginning like this:

import editor.textfiles.CsvFile;
or
import editor.textfiles.*; 
to import everything from that package.

Simple, isn't it?
I still think Lisp is a better language though :)
From: Edi Weitz
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <87of0b87o0.fsf@bird.agharta.de>
·········@gmx.net (thelifter) writes:

> Excuse me for mentioning Java here, but IMHO it has created a simple
> and powerfull way of handling packages. The idea of associating the
> package name with the directory structure was a good design
> decision.

Java has created this? At least Perl also has this, i.e. if you

  use Foo::Bar

Perl is looking for a file "../Foo/Bar.pm" in its @INC path. I wonder
which one was first and if there has been prior art. (Just curious, I
don't know the answer.)

> For those who don't know Java a short explanation:
> 
> In Java everything has to be in a package. The first line of a Java
> source file names the package like:
> 
> Package editor.textfiles;
> 
> public class CsvFile{...
> 
> This means that your source File has to be in a path that ends with
> 
> .../editor/textfiles/CsvFile.java
> 
> To use another package in your program, you use the import statement
> at the beginning like this:
> 
> import editor.textfiles.CsvFile;
> or
> import editor.textfiles.*; 
> to import everything from that package.
> 
> Simple, isn't it?

  ···@bird:/tmp > java -version
  java version "1.4.2"
  Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
  Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)
  ···@bird:/tmp > cat test.java
  import java.util.regex.*;

  class test {
    public static void main(String[] args) {
      if (Pattern.compile("a*b").matcher("aaab").matches()) {
        System.out.println("Yep!");
      }
    }
  }
  ···@bird:/tmp > javac test.java
  ···@bird:/tmp > java test
  Yep!
  ···@bird:/tmp > cat test2.java
  import java.util.*;

  class test2 {
    public static void main(String[] args) {
      if (Pattern.compile("a*b").matcher("aaab").matches()) {
        System.out.println("Yep!");
      }
    }
  }
  ···@bird:/tmp > javac test2.java
  test2.java:5: cannot resolve symbol
  symbol  : variable Pattern
  location: class test2
      if (Pattern.compile("a*b").matcher("aaab").matches()) {
          ^
  1 error
  ···@bird:/tmp >

Simple? To me it looks counter-intuitive at first glance.

Edi.
From: Oleg Goldshmidt
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <m3brwarm6s.fsf@zaphod.goldshmidt.org>
Edi Weitz <···@agharta.de> writes:

> ·········@gmx.net (thelifter) writes:
> 
> > Excuse me for mentioning Java here, but IMHO it has created a simple
> > and powerfull way of handling packages. The idea of associating the
> > package name with the directory structure was a good design
> > decision.

IMHO it was a design decision made under heavy influence of something
adversely affecting higher brain function. Now you cannot rename a
file or change your code's directory structure without breaking
*client code at the source level*. Introducing project management
elements, such as "where do I look for the source files I need?", into
code breaks an important abstraction and makes a developer's life
significantly more frustrating than it should be. Been there, suffered
through that.

Another, less immediate problem is that this approach assumes something
about the directory structure of the host system. This is in a sharp
contrast to, say, C, that consciously leaves the effect of

#include "jni.h"

implementation dependent, leaving it to the host system to decide what
it means and how to find it, and allowing flexibility at a level that
leaves the code invariant. Just for the fun of it I hope there will 
be (or maybe there is already) an OS/filesystem that will be
incompatible with the hierarchical structure Java assumes. 

-- 
Oleg Goldshmidt | ···@NOSPAM.goldshmidt.org
From: Pascal Costanza
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <costanza-3FB068.02200504072003@news.netcologne.de>
In article <····························@posting.google.com>,
 ·········@gmx.net (thelifter) wrote:

> Excuse me for mentioning Java here, but IMHO it has created a simple
> and powerfull way of handling packages. The idea of associating the
> package name with the directory structure was a good design decision.

Packages in Common Lisp and packages in Java have some overlaps, but 
they are generally solving different problems. You can't compare them 
just because they happen to have similar names.

Common Lisp's package system deals with bundling of symbols and, hence, 
allows for bundling definitions as a "side effect", but does not deal 
with searching and loading of system parts at all. In Common Lisp 
terminology, the latter task is called "system construction".

Further note that even in Java, "system construction" is typically 
handled by more complex tools (like ANT) for large projects.

Google for ASDF and DEFSYSTEM to see how system construction is handled 
in Common Lisp. Somewhere in the middle of 
http://groups.google.com/groups?selm=sfwadt7rm61.fsf%40shell01.TheWorld.c
om there is a nice example of what you can do with packages in Common Lisp.


Pascal
From: ·············@attbi.com
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <he62ca9p.fsf@attbi.com>
·········@gmx.net (thelifter) writes:

> Excuse me for mentioning Java here, but IMHO it has created a simple
> and powerfull way of handling packages.  The idea of associating the
> package name with the directory structure was a good design decision.

The idea of associating a package name with a directory structure is a
*terrible* decision.

To give a simple example, suppose you have two configurations for your
editor file (perhaps you have a product that is released under
different java engines on different platforms).  If you source file
names a package like:

> Package editor.textfiles;
>
> public class CsvFile{...
>
> This means that your source File has to be in a path that ends with
>
> .../editor/textfiles/CsvFile.java

But you want TWO different source files, both named CsvFile.java, but
one for each configuration.  Unfortunately, your file system cannot
handle two files with the same name.

In a complicated product, this comes up again and again.
From: Henrik Motakef
Subject: Re: Idiot's guide to packages
Date: 
Message-ID: <pan.2003.07.04.21.08.08.59366@henrik-motakef.de>
On Fri, 04 Jul 2003 21:22:27 +0000, prunesquallo wrote:

>> Excuse me for mentioning Java here, but IMHO it has created a simple and
>> powerfull way of handling packages.  The idea of associating the package
>> name with the directory structure was a good design decision.
> 
> The idea of associating a package name with a directory structure is a
> *terrible* decision.

It is also completely unsuitable for Lisp for at least two other reasons:

- Code doesn't have to come from a file. In what package would a function
  defined in the REPL be? Based on *default-pathname-defaults*? ;-)
- What happens if you define a class my-pkg:foo and want to specialize
  cl:shared-initialize on it? Does the method have to be in another file
  in a "common-lisp" directory?

Combine that with the stupid recommendation to use DNS names for package
names (/and/ not allowing all characters valid in DNS names), and the Java
package system looks rather weird.