Search code examples
common-lisp

Export / unintern and symbol access


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?


Solution

  • 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:

    • either it is directly present because
      • it either has the current package as its home package
      • or it has been imported into it from some other package,
    • or it is accessible by inheritance due to the current package using some other package.

    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