Just about where the trouble begins.
This commit is contained in:
parent
c6d958e6a0
commit
0d29b9e591
@ -1120,3 +1120,215 @@
|
|||||||
lists maintained in the packages play a "dual" role in the packaging system,
|
lists maintained in the packages play a "dual" role in the packaging system,
|
||||||
the list of /external/ symbols and the list of /used/ packages. The following
|
the list of /external/ symbols and the list of /used/ packages. The following
|
||||||
function gives the list of the external symbols of a package.
|
function gives the list of the external symbols of a package.
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
*package*
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(defun package-external-symbols (package)
|
||||||
|
(let ((rslt nil))
|
||||||
|
(do-external-symbols (s package)
|
||||||
|
(push s rslt))
|
||||||
|
rslt))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
The evaluation of the first expression is just to confirm that the default
|
||||||
|
package remains ="P1"=. Let us see what the lists of external symbols of the
|
||||||
|
packages ="P1"=, ="CL-USER"= and ="COMMON-LISP"= are:
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(package-external-symbols "P1")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(package-external-symbols "CL-USER")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(subseq (package-external-symbols "COMMON-LISP") 0 10)
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(length (package-external-symbols "COMMON-LISP"))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
There are no external symbols in ="P1"= and ="CL-USER"=, but 978 such symbols
|
||||||
|
in the package ="COMMON-LISP"=. (Only the first ten are being displayed.) A
|
||||||
|
point of concern might be the following: these symbols are accessible via the
|
||||||
|
package ="COMMON-LISP"= and yet the double-colon notation
|
||||||
|
=common-lisp::simple-error= was not used. The explanation has two "dual"
|
||||||
|
parts:
|
||||||
|
|
||||||
|
1. The symbol =simple-error= is external in the package ="COMMON-LISP"=.
|
||||||
|
2. The package ="COMMON-LISP"= is in the =package-use-list= of the package
|
||||||
|
="P1"=:
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(multiple-value-list (find-symbol "SIMPLE-ERROR" "COMMON-LISP"))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(package-use-list "P1")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(package-nicknames (find-package "COMMON-LISP"))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
="CL"= is the nickname of the package whose official name is ="COMMON-LISP"=,
|
||||||
|
and which is not to be confused with ="COMMON-LISP-USER"=.
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(eq (find-package "CL")
|
||||||
|
(find-package "COMMON-LISP"))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(eq (print (find-package "CL"))
|
||||||
|
(print (find-package "CL-USER")))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Applied to a package $p$, the Lisp function [[http://clhs.lisp.se/Body/f_pkg_us.htm][=package-use-list=]] returns the
|
||||||
|
list of all the packages used by $p$. If $p_1$ uses $p_2$, then it is said
|
||||||
|
that $p_2$ is used by $p_1$. Whether this relation is reflexive can be
|
||||||
|
doubted (What does "$p$ uses $p$" mean?), and it is neither symmetric
|
||||||
|
("$p_1$ uses $p_2$" does not imply "$p_2$ uses $p_1$") nor transitive
|
||||||
|
("$p_1$ uses $p_2$" and "$p_2$ uses $p_3$” does not imply
|
||||||
|
"$p_1$ uses $p_3$"). The oriented graph of the /use/ relation is totally
|
||||||
|
arbitrary.
|
||||||
|
|
||||||
|
* First toy examples.
|
||||||
|
|
||||||
|
Let's start over with two "fresh" packages ="P1"= and ="P2"=.
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
|
||||||
|
(in-package "CL-USER")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :results value verbatim
|
||||||
|
(delete-package (find-package "P1"))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :results value verbatim
|
||||||
|
(defpackage "P1" (:use "CL"))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :results value verbatim
|
||||||
|
(defpackage "P2" (:use "CL"))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
We switch the default package to ="P1"=:
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :exports both :results value verbatim
|
||||||
|
(in-package "P1")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
and we assume that, /in this environment/, we define the functions
|
||||||
|
=package-internal-symbols= and =package-external-symbols= as explained
|
||||||
|
before.
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P1" :exports both :results value verbatim
|
||||||
|
(defun package-internal-symbols (package)
|
||||||
|
(let ((rslt))
|
||||||
|
(do-symbols (s package)
|
||||||
|
(when (eq (second
|
||||||
|
(multiple-value-list
|
||||||
|
(find-symbol (symbol-name s) package)))
|
||||||
|
:internal)
|
||||||
|
(push s rslt)))
|
||||||
|
rslt))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P1" :exports both :results value verbatim
|
||||||
|
(defun package-external-symbols (package)
|
||||||
|
(let ((rslt))
|
||||||
|
(do-external-symbols (s package)
|
||||||
|
(push s rslt))
|
||||||
|
rslt))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
What about the internal symbols of ="P1"=?
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P1" :exports both :results value verbatim
|
||||||
|
(package-internal-symbols "P1")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
We see the symbols naming our functions and also the symbols =rslt= and =s=
|
||||||
|
used to define them. All the other symbols used in their definitions are in
|
||||||
|
fact external in ="COMMON-LISP"= and absent here. We move now to the package
|
||||||
|
="P2"= from where we cannot access the symbol =package-internal-symbols=
|
||||||
|
directly.
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P1" :exports both :results value verbatim
|
||||||
|
(in-package "P2")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P2" :exports both :results value verbatim
|
||||||
|
(multiple-value-list (find-symbol "PACKAGE-INTERNAL-SYMBOLS" "P2"))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
We have already seen the use of the ='::'= notation to make reference to the
|
||||||
|
symbol at once. We can also /import/ the symbol, in which case it becomes
|
||||||
|
directly accessible from ="P2"= permanently:
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P2" :exports both :results value verbatim
|
||||||
|
(import 'p1::package-internal-symbols "P2")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P2" :exports both :results value verbatim
|
||||||
|
(package-internal-symbols "P2")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Another solution requires /two/ steps:
|
||||||
|
|
||||||
|
1. Make the symbol =external= in some package, which is the role of the Lisp
|
||||||
|
function [[http://clhs.lisp.se/Body/f_export.htm][=export=]].
|
||||||
|
2. Declare that the current package /uses/ the package where the symbol is
|
||||||
|
external.
|
||||||
|
|
||||||
|
Let us use this method to make the symbol =package-external-symbols= directly
|
||||||
|
visible from ="P2"=.
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P2" :exports both :results value verbatim
|
||||||
|
(export 'p1::package-external-symbols "P1")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P2" :exports both :results value verbatim
|
||||||
|
(use-package "P1" "P2")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P2" :exports both :results value verbatim
|
||||||
|
(package-external-symbols "P2")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P2" :exports both :results value verbatim
|
||||||
|
(package-external-symbols "P1")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
An =export= expression has the same form as an =import= one:
|
||||||
|
=(export= $sm$ $st$ =)=, where $sm$ is a symbol and $st$ is a string naming a
|
||||||
|
package. The symbol $sm$ must be readable from the current default package,
|
||||||
|
for us ="P2"=, which explains the (required) prefix ='p1::'=. The argument
|
||||||
|
$st$ is a string naming the package where the symbol $sm$ is to become
|
||||||
|
external. Again, the terminology is somewhat misleading: the function
|
||||||
|
=export= does not export anything. All it does is to make some connection
|
||||||
|
$st \rightarrow sm$ "exportable" to other packages via =use-package=
|
||||||
|
expressions. The 978 external symbols of ="COMMON-LISP"= contain all the
|
||||||
|
standard Lisp constants, variables and functions. Because an allocated
|
||||||
|
package is always initialized with the package ="COMMON-LISP"= in its
|
||||||
|
=package-use-list=, these basic Lisp objects will be accessible from any
|
||||||
|
package. If we remove ="COMMON-LISP"= from the =use-package-list= of the
|
||||||
|
current default package, via =unuse-package=, the situation becomes a little
|
||||||
|
tricky.
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P2" :exports both :results value verbatim
|
||||||
|
(common-lisp::import
|
||||||
|
'(common-lisp::progn common-lisp::ignore-errors common-lisp::multiple-value-list common-lisp::+)
|
||||||
|
"P2")
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC lisp :session pcl :package "P2" :exports both :results value verbatim
|
||||||
|
(unuse-package "COMMON-LISP" "P2")
|
||||||
|
#+END_SRC
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user