In the following example, I'm getting an error:
These symbols are not accessible in the COMMON-LISP-USER package:
(FOO::BAR)
yet,
LS-USER> (describe 'foo::bar)
FOO::BAR
[symbol]
; No value
Here's what how I got there:
CL-USER> (make-package "FOO" :use '())
#<PACKAGE "FOO">
CL-USER> (intern "BAR" *)
FOO::BAR
NIL
CL-USER> (export (find-symbol "BAR" (find-package "FOO")))
Now I understand what the error means and what I'm curious about is: "Is this behaviour correct according to the spec?". I'm using SBCL.
I can see why it's not accessible via foo:bar
(it's not exported). However since export
is given both the symbol and the package, why can't it access this symbol and export it? I'm seeing similar things with unintern
.
A close read says "export makes one or more symbols that are accessible in package ...". It doesnt' say it has to be accessible in the current package (*package*
).
It seems to me that export has all the information it needs to perform the export, but the only way this seems to work is with (export 'foo::bar (find-package "FOO"))
. Perhaps it's an underspecified area and this is just what SBCL has choosen to do?
This is entirely correct behaviour: anything else would be nonconformant. (export s)
will try to export the symbols designated by s
from the current package (the default for the optional second argument of export
), which is CL-USER
in your case. To do that those symbols must already be accessible in the current package. A symbol is accessible in the current package if:
In the final case it will first be imported and then exported.
None of these things is true in your case. The symbol you are designating, which is FOO::BAR
since symbols designate themselves, is not accessible in the CL-USER
package at all.
See the spec