From: Joris Bleys
Subject: package frenzy
Date: 
Message-ID: <2005053014035375249%jbleys@vubacbe>
Hello all!

I'm experiencing some problems using packages in Lisp and I'm wondering 
what your opinions are about the packages-facility in Lisp. I've been 
hearing around and most of my comrades suggest not to use packages. I'd 
like to use them to avoid nasty things like name-clashes (that's what 
they're for, right?). Is there any guide on how packages should be used?

Description of the problem I ran into:

Let's say I have some package :exporting-package, which has two 
functions: ep-internal-fn and ep-external-fn. The ep-internal-fn gets a 
string as argument and returns a symbol using (read-line str NIL NIL). 
The ep-external-fn uses eq to compare the result of ep-internal-fn with 
a pre-programmed symbol 'TEST. The ep-external-fn is exported.

Now another package is defined :importing-package which uses the 
:exporting-package (use-package). When ep-external-fn is called, the 
equality is always false. This happens because the result of 
ep-external-fn is a symbol in the package :importing-package, whereas 
the 'TEST symbol is defined in the :exporting-package.

Many thanks in advance,

Joris Bleys

From: Paul F. Dietz
Subject: Re: package frenzy
Date: 
Message-ID: <YPudnQRlKNdFmAbfRVn-ow@dls.net>
Joris Bleys wrote:
> Hello all!
> 
> I'm experiencing some problems using packages in Lisp and I'm wondering 
> what your opinions are about the packages-facility in Lisp. I've been 
> hearing around and most of my comrades suggest not to use packages. I'd 
> like to use them to avoid nasty things like name-clashes (that's what 
> they're for, right?). Is there any guide on how packages should be used?

No, you absolutely should use packages.  Programming in the CL-USER
package means your code cannot be integrated with others who do the
same, and is possibly nonportable anyway since implementations can
stick any symbols they want in that package.

I typically make the packages fairly large, and put their definitions
off in their own files, but this is style.

It's a good idea to avoid using the :: package prefixes when possible.
That's a sign that someone is cheating and going behind the back
of a package's public interface.


> Let's say I have some package :exporting-package, which has two 
> functions: ep-internal-fn and ep-external-fn. The ep-internal-fn gets a 
> string as argument and returns a symbol using (read-line str NIL NIL). 
> The ep-external-fn uses eq to compare the result of ep-internal-fn with 
> a pre-programmed symbol 'TEST. The ep-external-fn is exported.
> 
> Now another package is defined :importing-package which uses the 
> :exporting-package (use-package). When ep-external-fn is called, the 
> equality is always false. This happens because the result of 
> ep-external-fn is a symbol in the package :importing-package, whereas 
> the 'TEST symbol is defined in the :exporting-package.

That symbol was part of the API of the exported function, so it itself
should have been exported also.  Or, you could have used a keyword
symbol.

(Also be careful when calling READ-LINE that you've bound *PACKAGE*
appropriately.)

	Paul
From: Joris Bleys
Subject: Re: package frenzy
Date: 
Message-ID: <2005053014435616807%jorisb@artivubacbe>
On 2005-05-30 14:23:50 +0200, "Paul F. Dietz" <·····@dls.net> said:

>> I'd like to use them to avoid nasty things like name-clashes (that's 
>> what they're for, right?).
> 
> No, you absolutely should use packages.

Ok, so we tend to agree :).

> 
>> Let's say I have some package :exporting-package, which has two 
>> functions: ep-internal-fn and ep-external-fn. The ep-internal-fn gets a 
>> string as argument and returns a symbol using (read-line str NIL NIL). 
>> The ep-external-fn uses eq to compare the result of ep-internal-fn with 
>> a pre-programmed symbol 'TEST. The ep-external-fn is exported.
>> 
>> Now another package is defined :importing-package which uses the 
>> :exporting-package (use-package). When ep-external-fn is called, the 
>> equality is always false. This happens because the result of 
>> ep-external-fn is a symbol in the package :importing-package, whereas 
>> the 'TEST symbol is defined in the :exporting-package.
> 
> That symbol was part of the API of the exported function, so it itself
> should have been exported also.  Or, you could have used a keyword
> symbol.

Maybe, I was a bit unclear with my problem statement. The symbol is not 
part of the API and should remain unvisible for the users of 
:exporting-package. So I guess what I want to do is to make sure that 
the result of the call to the read-line fn returns a symbol inside the 
:exported-package, but I don't know how to do so. Both ep-internal-fn 
and ep-external-fn are defined in the package :exporting-package (using 
in-package).

> 	Paul

Thanks for your support!

Joris
From: Paul F. Dietz
Subject: Re: package frenzy
Date: 
Message-ID: <EZudnWqYEsbGkgbfRVn-ow@dls.net>
Joris Bleys wrote:

>  So I guess what I want to do is to make sure that 
> the result of the call to the read-line fn returns a symbol inside the 
> :exported-package, but I don't know how to do so. Both ep-internal-fn 
> and ep-external-fn are defined in the package :exporting-package (using 
> in-package).

Ah!  The reader will intern symbols in the package
indicated by the special variable *PACKAGE*.  At runtime, this
could be anything (not necessarily either of your two packages).
To control that, bind *PACKAGE* around the READ-LINE call:

   (let ((*package* <desired-package>))
     (read-line str nil nil))

	Paul
From: Joris Bleys
Subject: Re: package frenzy
Date: 
Message-ID: <2005053015574143658%jorisb@artivubacbe>
On 2005-05-30 15:04:25 +0200, "Paul F. Dietz" <·····@dls.net> said:

> Ah!  The reader will intern symbols in the package
> indicated by the special variable *PACKAGE*.  At runtime, this
> could be anything (not necessarily either of your two packages).

Ok, thanks for your reply!

Joris
From: Peter Seibel
Subject: Re: package frenzy
Date: 
Message-ID: <m3d5r8na7h.fsf@gigamonkeys.com>
Joris Bleys <······@arti.vub.ac.be> writes:

> On 2005-05-30 14:23:50 +0200, "Paul F. Dietz" <·····@dls.net> said:
>
>>> I'd like to use them to avoid nasty things like name-clashes
>>> (that's what they're for, right?).
>> No, you absolutely should use packages.
>
> Ok, so we tend to agree :).
>
>> 
>>> Let's say I have some package :exporting-package, which has two
>>> functions: ep-internal-fn and ep-external-fn. The ep-internal-fn
>>> gets a string as argument and returns a symbol using (read-line str
>>> NIL NIL). The ep-external-fn uses eq to compare the result of
>>> ep-internal-fn with a pre-programmed symbol 'TEST. The
>>> ep-external-fn is exported.
>>> Now another package is defined :importing-package which uses the
>>> :exporting-package (use-package). When ep-external-fn is called,
>>> the equality is always false. This happens because the result of
>>> ep-external-fn is a symbol in the package :importing-package,
>>> whereas the 'TEST symbol is defined in the :exporting-package.
>> That symbol was part of the API of the exported function, so it
>> itself
>> should have been exported also.  Or, you could have used a keyword
>> symbol.
>
> Maybe, I was a bit unclear with my problem statement. The symbol is
> not part of the API and should remain unvisible for the users of
> :exporting-package. So I guess what I want to do is to make sure that
> the result of the call to the read-line fn returns a symbol inside the
> :exported-package, but I don't know how to do so. Both ep-internal-fn
> and ep-external-fn are defined in the package :exporting-package
> (using in-package).

For starters, presumably you're using READ not READ-LINE as the latter
returns a string, not a symbol. Or you're using READ-LINE and then
INTERN to create a symbol, which is arguably a better plan that using
READ so you don't have to worry about READ reading some other kind of
object. At any rate, the problem you're having is that READ and INTERN
both use the runtime value of *PACKAGE* to determine how to
find/intern symbols. So it doesn't matter that ep-internal-fn happens
to be defined in a file that is read with a particular *PACKAGE*--what
matters is what *PACKAGE* is when it is called. However you can fix
this easily enough:

  (defun ep-internal-fn (stream)
    (let ((*package* (find-package :the-package-you-want)))
      (read in nil nil)))

or

  (defun ep-internal-fn (stream)
    (let ((string (read-line in nil nil)))
      (when string
        (intern string :the-package-you-want))))

Note, in the later version you'll probably want to use (string-upcase
string) as the argument to INTERN in order to match the reader's
default upcasing of symbol names, i.e.

  (defun ep-internal-fn (stream)
    (let ((string (read-line in nil nil)))
      (when string
        (intern (string-upcase string) :the-package-you-want))))

-Peter

-- 
Peter Seibel                                     ·····@gigamonkeys.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Joris Bleys
Subject: Re: package frenzy
Date: 
Message-ID: <2005053015561550073%jorisb@artivubacbe>
Hi Peter,

> For starters, presumably you're using READ not READ-LINE as the latter
> returns a string, not a symbol. Or you're using READ-LINE and then
> INTERN to create a symbol, which is arguably a better plan that using
> READ so you don't have to worry about READ reading some other kind of
> object.

Actually I'm using (read-from-string "COMMAND extra stuff which ain't 
important" NIL NIL) which returns COMMAND as a symbol. I initially 
mispelled this as I thought this was not of major influence on my 
problem at hand).

> At any rate, the problem you're having is that READ and INTERN
> both use the runtime value of *PACKAGE* to determine how to
> find/intern symbols. So it doesn't matter that ep-internal-fn happens
> to be defined in a file that is read with a particular *PACKAGE*--what
> matters is what *PACKAGE* is when it is called.

Ok, I agree to you this indeed is the problem and the solution. I just 
find it a bit difficult for a programmer to make sure symbols are 
created in the right package. I wonder when calling an internal 
function, the *package* is not automatically changed to the package to 
the one in which it was defined.

Thanks for your help!

Joris
From: Peter Seibel
Subject: Re: package frenzy
Date: 
Message-ID: <m3mzqclcly.fsf@gigamonkeys.com>
Joris Bleys <······@arti.vub.ac.be> writes:

> Hi Peter,
>
>> For starters, presumably you're using READ not READ-LINE as the latter
>> returns a string, not a symbol. Or you're using READ-LINE and then
>> INTERN to create a symbol, which is arguably a better plan that using
>> READ so you don't have to worry about READ reading some other kind of
>> object.
>
> Actually I'm using (read-from-string "COMMAND extra stuff which ain't
> important" NIL NIL) which returns COMMAND as a symbol. I initially
> mispelled this as I thought this was not of major influence on my
> problem at hand).
>
>> At any rate, the problem you're having is that READ and INTERN
>> both use the runtime value of *PACKAGE* to determine how to
>> find/intern symbols. So it doesn't matter that ep-internal-fn happens
>> to be defined in a file that is read with a particular *PACKAGE*--what
>> matters is what *PACKAGE* is when it is called.
>
> Ok, I agree to you this indeed is the problem and the solution. I just
> find it a bit difficult for a programmer to make sure symbols are
> created in the right package. I wonder when calling an internal
> function, the *package* is not automatically changed to the package to
> the one in which it was defined.

So one nit-picky, but actually quite important point, is that's it
doesn't really make sense to talk of the package in which a function
was defined. For instance, in what package is this function defined:

  (in-package :foo)

  (defun bar::baz () 'hello)

The value of *PACKAGE* when this file is read will be the package
"FOO" but the name of the function BAZ will not be interned in
"FOO"[1]. So, in your dream Lisp, should *PACKAGE* be bound to the
package "FOO" or the package "BAR" when BAZ is called? That's a
rhetorical question--I'm sure you could come up with an answer and
maybe even make a case for why it makes more sense than the other
answer. But the fact of the matter is, that functions aren't "in"
packages--just their names. It's worth getting this straight in your
head because once you realize that packages are *just* a scheme for
managing names, and only indirectly the things they name, the package
system will make a lot more sense.

-Peter

[1] Well it could, if the "FOO" and "BAR" packages had the appropriate
relationships established. But leave that aside for the moment.


P.S. If you really want to define packages that rebind *PACKAGE* at
runtime to the package that was current when the function was defined,
you could define this macro:

  (defmacro defun/package (name (&rest args) &body body)
    `(defun ,name ,args
       (let ((*package* ,*package*))
         ,@body)))

And if you want functions that bind *PACKAGE* to the HOME package of
the name of the function, you could define this one:

  (defmacro defun/package (name (&rest args) &body body)
    `(defun ,name ,args
       (let ((*package* ,(symbol-package name)))
         ,@body)))

I'm not sure that either of these are particularly useful--it's
probably better to be explicit about what package you are using at
runtime to lookup/intern names.

-- 
Peter Seibel                                     ·····@gigamonkeys.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Joris Bleys
Subject: Re: package frenzy
Date: 
Message-ID: <2005053109110916807%jorisb@partmapsartivubacbe>
Hi Peter,

> It's worth getting this straight in your
> head because once you realize that packages are *just* a scheme for
> managing names, and only indirectly the things they name, the package
> system will make a lot more sense.

Thanks for you excellent guidance, I realized it was just about names 
but did not realise all the implications it has to write descent Lisp 
code. With your help it all makes a bit more sense now.

Thanks again!

Joris
From: Pascal Costanza
Subject: Re: package frenzy
Date: 
Message-ID: <3g0gv7F9t0dnU1@individual.net>
Joris Bleys wrote:

> Maybe, I was a bit unclear with my problem statement. The symbol is not 
> part of the API and should remain unvisible for the users of 
> :exporting-package. So I guess what I want to do is to make sure that 
> the result of the call to the read-line fn returns a symbol inside the 
> :exported-package, but I don't know how to do so. Both ep-internal-fn 
> and ep-external-fn are defined in the package :exporting-package (using 
> in-package).

Maybe you want (intern string :exporting-package) instead of read-line?

But indeed this sounds like a strange attempt. It sounds as if you 
wanted to use packages just to get more efficient string comparisons. 
Wouldn't a hashtable be good enough for such a purpose?

If you rely on "TEST" giving you some specialized behavior, that would 
indeed be part of your interface...

Pascal

-- 
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/
From: Pascal Costanza
Subject: Re: package frenzy
Date: 
Message-ID: <3g0ig4F9v8raU1@individual.net>
Pascal Costanza wrote:
> Joris Bleys wrote:
> 
>> Maybe, I was a bit unclear with my problem statement. The symbol is 
>> not part of the API and should remain unvisible for the users of 
>> :exporting-package. So I guess what I want to do is to make sure that 
>> the result of the call to the read-line fn returns a symbol inside the 
>> :exported-package, but I don't know how to do so. Both ep-internal-fn 
>> and ep-external-fn are defined in the package :exporting-package 
>> (using in-package).
> 
> Maybe you want (intern string :exporting-package) instead of read-line?

That was a brain fart. Sorry. ;)


Pascal

-- 
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/
From: Joris Bleys
Subject: Re: package frenzy
Date: 
Message-ID: <2005053015424475249%jorisb@artivubacbe>
Hi Pascal,

Don't I know you from somewhere? ;)

>> Maybe, I was a bit unclear with my problem statement. The symbol is not 
>> part of the API and should remain unvisible for the users of 
>> :exporting-package. So I guess what I want to do is to make sure that 
>> the result of the call to the read-line fn returns a symbol inside the 
>> :exported-package, but I don't know how to do so. Both ep-internal-fn 
>> and ep-external-fn are defined in the package :exporting-package (using 
>> in-package).

Ok, I tried to abstract my problem a bit, trying to make the problem as 
clear as possible, but my attempt ended in a disaster :).

The :exporting-package really is a client. This client uses simple 
crlf-ended lines over a tcp-connection. Now for extracting the commands 
they receive, the first word of this line always resembles the command 
sended and is implemented in ep-internal-fn (the real name is
reply->command. It is actually implemented as a (read-from-string reply 
nil nil).

The ep-external-fn is of a higher-level like 'start-client' and checks 
the incoming commands from the server are eq to the expected command. 
So the comparisons are used inside the ep-external-fn and should not be 
visible to the user of the :exporting-package.

> Maybe you want (intern string :exporting-package) instead of read-line?

This might indeed be the function I'm looking for. It seems more 
elegant than setting *package* by hand. Oops, just read your reply :p, 
so I might look very stupid now :). But I indeed want to make the 
read-from-string result internal. Problem is, that has got no name, as 
it is just past as the return value of a function straight in the 
eq-test.

However, doing so requires the programmer to be realy careful when 
employing packages. I'd like to think that calling internal functions 
should automagically change the *package* to the package it was 
internal in, but I guess there are good reasons, which I don't yet 
fully (and might never :)) understand, for not doing so.

> But indeed this sounds like a strange attempt. It sounds as if you 
> wanted to use packages just to get more efficient string comparisons. 
> Wouldn't a hashtable be good enough for such a purpose?

This package is actually used to get to a higher level of commands and 
thus does more than a simple string comparisons. Hashtables are a good 
idea, but the protocol used is very straight forward and this might 
result in overkill, at least in the client.

Thanks for your advice and the time for writing it down!

Joris
From: Pascal Costanza
Subject: Re: package frenzy
Date: 
Message-ID: <3g0njrFa2napU1@individual.net>
Joris Bleys wrote:
> Hi Pascal,
> 
> Don't I know you from somewhere? ;)

That must be a coincidence. ;)

>> Maybe you want (intern string :exporting-package) instead of read-line?
> 
> This might indeed be the function I'm looking for. It seems more elegant 
> than setting *package* by hand. Oops, just read your reply :p, so I 
> might look very stupid now :).

Maybe we both do. ;)

> However, doing so requires the programmer to be realy careful when 
> employing packages. I'd like to think that calling internal functions 
> should automagically change the *package* to the package it was internal 
> in, but I guess there are good reasons, which I don't yet fully (and 
> might never :)) understand, for not doing so.

It's not that hard to understand. You have to get two things straight:

- When the Lisp reader reads in your source code (the original source 
code, not what you want to do at runtime), it uses *package* to 
determine the package of the symbols that are part of your source code. 
That's the sole purpose of *package*. You can reuse that functionality 
for your own stuff at runtime, but you have to imitate that behavior (so 
bind *package* correctly, or use INTERN with a second parameter 
appropriately). Read time and runtime are just two different times for a 
Lisp program, and you just have to keep them separated in your head.

- It might have been possible to automagically rebind *package*, 
whenever a function is called, to the home package of the symbol whose 
symbol-function is that function at runtime. This would incur a serious 
overhead though, and you would have to care about obvious and not so 
obvious corner cases. For example, what happens when you call an 
anonymous function? What if you change the fdefinition of a function at 
runtime? etc.


Pascal

-- 
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/
From: Brian Downing
Subject: Re: package frenzy
Date: 
Message-ID: <nK1ne.22369$PS3.13015@attbi_s22>
In article <··························@artivubacbe>,
Joris Bleys  <······@arti.vub.ac.be> wrote:
> However, doing so requires the programmer to be realy careful when 
> employing packages. I'd like to think that calling internal functions 
> should automagically change the *package* to the package it was 
> internal in, but I guess there are good reasons, which I don't yet 
> fully (and might never :)) understand, for not doing so.

There are.  Most importantly, how would you avoid such behavior when you
don't want it?  (declare (do-not-automatically-frob-*package*
function-name))?  If *package* always changes to the home package of the
called function, it's impossible to implement READ and friends.  This
would definitely bug Lisp implementors, who usually implement READ in
Lisp.

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net> 
From: Paolo Amoroso
Subject: Re: package frenzy
Date: 
Message-ID: <874qck6ekl.fsf@plato.moon.paoloamoroso.it>
Joris Bleys <······@vub.ac.be> writes:

> name-clashes (that's what they're for, right?). Is there any guide on
> how packages should be used?

Have you checked the chapter on packages:

  21. Programming in the Large: Packages and Symbols
  http://www.gigamonkeys.com/book/programming-in-the-large-packages-and-symbols.html

in Peter Seibel's book?

  Practical Common Lisp
  http://www.gigamonkeys.com/book/


Paolo
-- 
Why Lisp? http://lisp.tech.coop/RtL%20Highlight%20Film
Recommended Common Lisp libraries/tools (see also http://clrfi.alu.org):
- ASDF/ASDF-INSTALL: system building/installation
- CL-PPCRE: regular expressions
- UFFI: Foreign Function Interface
From: Joris Bleys
Subject: Re: package frenzy
Date: 
Message-ID: <200505301600348930%jorisb@artivubacbe>
Hi Paolo!

> Peter Seibel's book?

I have gone through several references, but this one was missing in my list.

Thanks for pointing it out!

Joris