I am somewhat struggling with the package system. Here is an excerpt:
CL-USER> (in-package :cl-user)
#<PACKAGE "COMMON-LISP-USER">
CL-USER> (defpackage :foo (:use :cl) (:export :huhu))
#<PACKAGE "FOO">
CL-USER> (in-package :foo)
#<PACKAGE "FOO">
FOO> (defparameter *bar* 'bar)
*BAR*
FOO> (defun huhu ()
(list *bar* 'bar (read-from-string "bar")))
HUHU
FOO> (huhu)
(BAR BAR BAR)
FOO> (in-package :cl-user)
#<PACKAGE "COMMON-LISP-USER">
CL-USER> (foo:huhu)
(FOO::BAR FOO::BAR BAR)
CL-USER> (defpackage :baz)
#<PACKAGE "BAZ">
CL-USER> (in-package :baz)
#<COMMON-LISP:PACKAGE "BAZ">
BAZ> (foo:huhu)
(FOO::BAR FOO::BAR BAR)
BAZ>
So READ seems to put symbols into the "toplevel" package, while DEFPARAMETER
seems to honor the IN-PACKAGE setting.
Is there any way to tell READ to put the symbols into the FOO package?
> Is there any way to tell READ to put the symbols into the FOO package?
Be in that package (ie have the value of *package* be the package you
want to intern into) when you call READ, or use a package qualifier.
You will be puzzled for ever if you keep saying silly things such as
"DEFPARAMETER seems to honor the IN-PACKAGE setting."
DEFPARAMETER doesn't care the lessa bout packages, as most of the rest
of CL.
What matters, is the binding of CL:*PACKAGE* when the DEFPARAMETER form
is _READ_.
Since you've bound CL:*PACKAGE* to #<PACKAGE "FOO"> when you had it read
the defparameter form, then the unqualified symbols *BAR* and BAR have
been interned into that FOO package. DEFPARAMETER just made FOO::*BAR*
be a special global variable bound to the symbol FOO::BAR.
READ or READ-FROM-STRING don't use the "toplevel" package, but the
current dynamic binding of the CL:*PACKAGE* variable. So you could for
example write:
(let ((a (let ((*package* (find-package :foo))) (read-from-string "baz")))
(b (let ((*package* (find-package :baz))) (read-from-string "baz"))))
(list (string= a b) (eql a b) a b))
--> (T NIL FOO::BAZ BAZ::BAZ)
--
__Pascal Bourguignon__ http://www.informatimago.com/
Well, for starters, DEFPARAMETER doesn't really know anything about
packages and it doesn't care. Packages affect the way the reader
converts strings into symbols. So the real issue is what package is the
"current package" when the reader encounters a string that it needs to
turn into a symbol.
There are essentially two levels to this. The first is an explicit
package designation, using : or :: to indicate the package in which a
symbol is supposed to be accessible.[1] That is used to find an
appropriately matching symbol (which may actually be in a different
package)[2] or to indicate in which package a new symbol is created. If
there is no explicit package indicated, then the current value of
*package* is used
IN-PACKAGE is one way of setting the current package, which is kept in
the variable CL:*PACKAGE*.
> Is there any way to tell READ to put the symbols into the FOO package?
So, yes, there are a couple of ways to do this. One of the simplest is
to just use a package prefix:
(defun huhu ()
(list *bar* 'bar (read-from-string "foo::bar")))
By the way, the reason *bar* and 'bar are in the FOO package is because
that is the current package when this form is READ by the reader before
being passed on to the evaluator (or compiler). Remember that it is the
reading process that determines in which package symbols in the code end
up.[3] And since there was an (in-package :foo) before this code was
read, the current package was set to FOO.
So, explicit qualification works if you have a constant string to read.
If you want to process an arbitrary string in a particular package, you
can bind *package* to the package you want:
(defun huhu ()
(let ((*package* (find-package "FOO")))
(list *bar* 'bar (read-from-string "bar"))))
=========== Notes ===========
[1] There is also #: to indicate to tell the reader to not intern the
symbol in a package at all.
[2] The package qualifier indicates the package in which the lookup of
an existing symbol occurs. So if there is an explicitly or implicitly
imported symbol that matches, it will be returned even if it is in a
different package. In that way cl-user::car and cl:car are the same
symbol.
[3] OK, there are program calls like INTERN that can also do this, but
we aren't using them in this example.
--
Thomas A. Russ, USC/Information Sciences Institute
I'm saying silly things because I try to express the problem in my own
words. Sorry for not being a CL expert...
> DEFPARAMETER doesn't care the lessa bout packages, as most of the rest
> of CL.
>
> What matters, is the binding of CL:*PACKAGE* when the DEFPARAMETER form
> is _READ_.
>
> Since you've bound CL:*PACKAGE* to #<PACKAGE "FOO"> when you had it read
> the defparameter form, then the unqualified symbols *BAR* and BAR have
> been interned into that FOO package. DEFPARAMETER just made FOO::*BAR*
> be a special global variable bound to the symbol FOO::BAR.
OK, I understand this.
> READ or READ-FROM-STRING don't use the "toplevel" package, but the
> current dynamic binding of the CL:*PACKAGE* variable. So you could for
> example write:
Oh, I totally forgot that this is a dynamic binding...