Dealing w/ packages in Org.

This commit is contained in:
Gerd Heber 2018-01-28 15:40:57 -06:00
parent fec84282fe
commit c0a5a2b7da

View File

@ -586,3 +586,173 @@
package should in principle be void of symbols. To make our experiments more package should in principle be void of symbols. To make our experiments more
understandable it is better to allocate and use toy packages. The understandable it is better to allocate and use toy packages. The
[[http://clhs.lisp.se/Body/m_defpkg.htm][=defpackage=]] function (a macro) allocates a package of a given name. [[http://clhs.lisp.se/Body/m_defpkg.htm][=defpackage=]] function (a macro) allocates a package of a given name.
#+BEGIN_SRC lisp :session pcl :exports both :results value verbatim
(defpackage "P1" (:use "CL"))
#+END_SRC
A package ="P1"= is now present in our environment, without any internal
symbols.
#+BEGIN_SRC lisp :session pcl :exports both :results value verbatim
(package-internal-symbols "P1")
#+END_SRC
(The symbol =nil= also represents the empty list.) Let's allocate a few
symbols and make them internal in the package ="P1"=! The current default
package is ="COMMON-LISP-USER"= and we switch it to ="P1"= like this:
#+BEGIN_SRC lisp :session pcl :exports both :results value verbatim
(in-package "P1")
#+END_SRC
#+BEGIN_SRC lisp :session pcl :exports both :package "P1"
*package*
#+END_SRC
From now on, the default package is ="P1"=. If we write down a symbol then it
will be understood by the Lisp reader as accessed via the package ="P1"=,
that is, unless we use a special syntax. Let us create a list of three
symbols and assign it to the symbol =list=, and then examine the internal
symbols of the package ="P1"=:
#+BEGIN_SRC lisp :session pcl :exports both :package "P1"
(multiple-value-list
(ignore-errors
(setf (symbol-value 'list) '(symb1 symb2 symb3))))
#+END_SRC
The reader probably would prefer =(defvar list)= followed by
=(setf list ...)=, which is rejected by some Lisp implementations, in
particular SBCL, because in principle the symbol =list=, owned by the package
="COMMON-LISP"=, is "locked". It is possible to unlock such a symbol, which
is a little technical, but using =(symbol-value 'list)= as above gets the job
done.
#+BEGIN_SRC lisp :session pcl :exports both :package "P1"
(multiple-value-list
(ignore-errors
(package-internal-symbols "P1")))
#+END_SRC
Oops! What happened? We've successfully used the function
=package-internal-symbols= earlier and suddenly it seems to have disappeared
from the environment. The point is that it was /defined when/
="COMMON-LISP-USER"= was the default package. Let us examine the situation!
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
(multiple-value-list (find-symbol "PACKAGE-INTERNAL-SYMBOLS" "COMMON-LISP-USER"))
#+END_SRC
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
(multiple-value-list (find-symbol "PACKAGE-INTERNAL-SYMBOLS" "P1"))
#+END_SRC
A symbol with the given name is found in both packages. Before encountering
the undefined functional value error, Lisp ( more precisely, the Lisp reader)
had interned a /new/ symbol with the name ="PACKAGE-INTERNAL-SYMBOLS"= in the
current default package, ="P1"=, for the sole reason that it was present in
the source text. Let us verify that both symbols are different!
#+BEGIN_SRC lisp :session pcl :exports both :package "P1"
(eq (find-symbol "PACKAGE-INTERNAL-SYMBOLS" "COMMON-LISP-USER")
(find-symbol "PACKAGE-INTERNAL-SYMBOLS" "P1"))
#+END_SRC
The symbols are different. Compare that with the status of =nil=, where the
same symbol =nil= was accessible via ="COMMON-LISP"= and via
="COMMON-LISP-USER"=. In our present situation both symbols are /different/,
and so are their respective properties. For example, the first symbol does
have a functional value and the second does not, which can be tested with the
function [[http://clhs.lisp.se/Body/f_fbound.htm][=fboundp=]]x:
#+BEGIN_SRC lisp :session pcl :exports both :package "P1"
(fboundp (find-symbol "PACKAGE-INTERNAL-SYMBOLS" "COMMON-LISP-USER"))
#+END_SRC
#+BEGIN_SRC lisp :session pcl :exports both :package "P1"
(fboundp (find-symbol "PACKAGE-INTERNAL-SYMBOLS" "P1"))
#+END_SRC
This is the first time we have seen the double-colon =‘::’= notation: When
the symbol =package-internal-symbols= was searched via ="COMMON-LISP-USER"=,
the answer was positive but the returned symbol was a little lengthy:
=COMMON-LISP-USER::PACKAGE-INTERNAL-SYMBOLS=. The current default package is
="P1"=, via which /this/ symbol is not accessible. However, we may access it
using the double-colon notation:
#+BEGIN_CENTER
=package-name::symbol-name=
#+END_CENTER
This is one of the methods which allows the user or Lisp to refer to a symbol
not accessible via the default package. The Lisp reader is told: "We mean the
symbol =symbol-name= via the package =package-name=." In contrast, for the
symbol with the same name but interned in the different ="P1"= package,
because ="P1"= is the current default package, the double colon notation is
not necessary. The longer notation lets us access a symbol interned in the
="COMMON-LISP-USER"= package and its functional value as follows:
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
(cl-user::package-internal-symbols "P1")
#+END_SRC
The =cl-user::= prefix tells Lisp to look for the symbol via the ="CL-USER"=
package (Remember that ="CL-USER"= is a nickname for ="COMMON-LISP-USER"=?)
and, because of its position just after a left parenthesis, to use its
functional value. Currently, there are four internal symbols in the package
="P1"= and they are returned in an arbitrary order. By the way, what about
the symbol =list=, to which we assigned a list (!) of symbols?
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
(multiple-value-list (find-symbol "LIST" "P1"))
#+END_SRC
The symbol is accessible via the package ="P1"= but with a different status,
the status /inherited/. We will examine this situation later. In fact, the
symbol =list=, one of the most important symbols in Lisp, is already present
in the package ="COMMON-LISP"= at the beginning of a session, and by default
accessible from any package.
We must mention also that our function $\rho$, or the function =find-symbol=
if you prefer, is (almost) injective /with respect to/ $st$. Let $p_1$ and
$p_2$ be two packages, $st_1$ and $st_2$ two strings. Then if
$\rho(p_1, st_1) = \rho(p_2, st_2)\neq\mathtt{nil}$, then $st_1 = st_2$. Pay
attention to the fact that the equality is an equality between /symbols/.
This is a consequence of $\mathtt{symbol-name}(\rho(p, st)) = st$; in other
words, there is no possibility of nicknames for a symbol name. In particular,
there is a 1-1 correspondence between the internal symbols of a package and
their respective names.
* Importing a symbol.
Instead of using the lengthy notation =cl-user::xxx= to make an internal
symbol in ="CL-USER"= accessible from ="P1"=, we may opt to /import/ this
symbol in the package ="P1"=. However, in doing so there is another problem
due to a name conflict, a point which will be examined in detail later:
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
(multiple-value-list
(ignore-errors
(import 'cl-user::package-internal-symbols "P1")))
#+END_SRC
The problem is a "collision" between two /different/ symbols, which cannot
coexist as internal symbols in the /same/ package ="P1"= with the /same/
name. Importing the symbol internal in ="CL-USER"= into the package ="P1"= is
not compatible with the current presence of /another/ symbol in ="P1"= with
the same =symbol-name=. We must first [[http://clhs.lisp.se/Body/f_uninte.htm][=unintern=]] the accidental, pre-existing
symbol in ="P1"= to "make room" for the symbol from ="CL-USER"=.
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
(unintern 'package-internal-symbols "P1")
#+END_SRC
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
(import 'cl-user::package-internal-symbols "P1")
#+END_SRC
#+BEGIN_SRC lisp :session pcl :exports both :package "P1" :results value verbatim
(package-internal-symbols "P1")
#+END_SRC