diff --git a/examples/pcl/Packages_in_Common_Lisp.org b/examples/pcl/Packages_in_Common_Lisp.org index c6fd4e2..cfb9162 100644 --- a/examples/pcl/Packages_in_Common_Lisp.org +++ b/examples/pcl/Packages_in_Common_Lisp.org @@ -87,13 +87,13 @@ we give a complete mathematical definition of this system as a set of mathematical formulas. -** Main sets of objects. +* Main sets of objects. - The first part of the packaging system is made of three disjoint sets: + The first part of the packaging system is made of three disjoint sets: - - The set $St$ of *strings*. - - The set $P$ of *packages*. - - The set $Sm$ of *symbols*. + - The set $St$ of *strings*. + - The set $P$ of *packages*. + - The set $Sm$ of *symbols*. In our description of the packaging system, the statuses of these sets are different. Think of the (infinite) set $St$ of /strings/ as made of /all/ @@ -115,356 +115,474 @@ Lisp session, and they are an essential component of the /current/ environment. -** Packages +* Packages - There is a simple, almost bijective (one-to-one), correspondence between - strings and packages, and a convenient place to start our subject. First, at - any time during a Lisp session, a /default package/ is defined and it can be - discovered via the global symbol [[http://clhs.lisp.se/Body/v_pkg.htm][=*package*=]]: + There is a simple, almost bijective (one-to-one), correspondence between + strings and packages, and a convenient place to start our subject. First, at + any time during a Lisp session, a /default package/ is defined and it can be + discovered via the global symbol [[http://clhs.lisp.se/Body/v_pkg.htm][=*package*=]]: - #+BEGIN_SRC lisp :session pcl :exports both - *package* - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + *package* + #+END_SRC - This is to be read as: the /value/ of the /symbol/ =*package*= is the - package whose /name/ is the string ="COMMON-LISP-USER"=. The types =symbol= - and =package= are system-defined, disjoint sets of machine objects. A symbol - is frequently used as a convenient intermediate object, which allows the - user to reach some object of arbitrary nature, its /value/. Here, - =*package*= is a symbol, the value of which is the package named - ="COMMON-LISP-USER"=. Technically, a symbol contains a pointer to its - (possible) value, here a package which happens to be the package used - ordinarily in a simple Lisp session. There are no facilities to refer to a - package object /directly/. However, one can use its /name/ and the function - [[http://clhs.lisp.se/Body/f_find_p.htm][=find-package=]] to obtain a reference: + This is to be read as: the /value/ of the /symbol/ =*package*= is the + package whose /name/ is the string ="COMMON-LISP-USER"=. The types =symbol= + and =package= are system-defined, disjoint sets of machine objects. A symbol + is frequently used as a convenient intermediate object, which allows the + user to reach some object of arbitrary nature, its /value/. Here, + =*package*= is a symbol, the value of which is the package named + ="COMMON-LISP-USER"=. Technically, a symbol contains a pointer to its + (possible) value, here a package which happens to be the package used + ordinarily in a simple Lisp session. There are no facilities to refer to a + package object /directly/. However, one can use its /name/ and the function + [[http://clhs.lisp.se/Body/f_find_p.htm][=find-package=]] to obtain a reference: - #+BEGIN_SRC lisp :session pcl :exports both - (find-package "COMMON-LISP-USER") - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (find-package "COMMON-LISP-USER") + #+END_SRC - Conversely, given a package, the function [[http://clhs.lisp.se/Body/f_pkg_na.htm][=package-name=]] returns its name: + Conversely, given a package, the function [[http://clhs.lisp.se/Body/f_pkg_na.htm][=package-name=]] returns its name: - #+BEGIN_SRC lisp :session pcl :exports both - (package-name (find-package "COMMON-LISP-USER")) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (package-name (find-package "COMMON-LISP-USER")) + #+END_SRC - The example was given to illustrate that the functions =find-package= and - =package-name= are the inverse of each other, defining a 1-1 correspondence - between the packages /currently/ defined in the environment and their - respective names, some character strings. Because of rules not of interest - here, it is common and convenient to use only uppercase character strings to - name packages. If a name does not correspond to any current package, the - =find-package= function returns the symbol =nil=, usually displayed - uppercase: + The example was given to illustrate that the functions =find-package= and + =package-name= are the inverse of each other, defining a 1-1 correspondence + between the packages /currently/ defined in the environment and their + respective names, some character strings. Because of rules not of interest + here, it is common and convenient to use only uppercase character strings to + name packages. If a name does not correspond to any current package, the + =find-package= function returns the symbol =nil=, usually displayed + uppercase: - #+BEGIN_SRC lisp :session pcl :exports both - (find-package "COMMON-LISP-user") - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (find-package "COMMON-LISP-user") + #+END_SRC - which illustrates that a package name is case-sensitive. Frequently, only a - few packages are in use, and because of their importance, descriptive names - are used. These descriptive names can be a little long, and it is possible - to define and use various /nicknames/ for these names. For example, the - ="COMMON-LISP-USER"= package usually has the nicknames ="CL-USER"= and - ="USER"=. The function [[http://clhs.lisp.se/Body/f_pkg_ni.htm][=package-nicknames=]] can be used to retrieve the list - of nicknames (strings) for a package, which doesn't include the name of the - package. + which illustrates that a package name is case-sensitive. Frequently, only a + few packages are in use, and because of their importance, descriptive names + are used. These descriptive names can be a little long, and it is possible + to define and use various /nicknames/ for these names. For example, the + ="COMMON-LISP-USER"= package usually has the nicknames ="CL-USER"= and + ="USER"=. The function [[http://clhs.lisp.se/Body/f_pkg_ni.htm][=package-nicknames=]] can be used to retrieve the list + of nicknames (strings) for a package, which doesn't include the name of the + package. - #+BEGIN_SRC lisp :session pcl :exports both - (find-package "COMMON-LISP-USER") - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (find-package "COMMON-LISP-USER") + #+END_SRC - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (package-nicknames (find-package "COMMON-LISP-USER")) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (package-nicknames (find-package "COMMON-LISP-USER")) + #+END_SRC - If a package is to be unambiguously identified by its name or one of its - nicknames, two different packages must have disjoint sets of - /name + nicknames/. + If a package is to be unambiguously identified by its name or one of its + nicknames, two different packages must have disjoint sets of + /name + nicknames/. -** Tracking a symbol. +* Tracking a symbol. - The Lisp symbols are very particular when compared to the identifiers of - other programming languages. They persist throughout the runtime of an - environment and are an important component of the power of Lisp. A package - is referenced via its name; the same goes for a symbol, but the process is - much more complex. The first and most common method to create or "to - /allocate/ a symbol" consists in just writing it down and passing it to the - Lisp reader using the standard Lisp conventions. In a Lisp environment, - there is a set of "pre-defined" symbols ready to be used. To caution the - reader about the complexity of the subject, we begin with a seemingly - strange example: + The Lisp symbols are very particular when compared to the identifiers of + other programming languages. They persist throughout the runtime of an + environment and are an important component of the power of Lisp. A package + is referenced via its name; the same goes for a symbol, but the process is + much more complex. The first and most common method to create or "to + /allocate/ a symbol" consists in just writing it down and passing it to the + Lisp reader using the standard Lisp conventions. In a Lisp environment, + there is a set of "pre-defined" symbols ready to be used. To caution the + reader about the complexity of the subject, we begin with a seemingly + strange example: - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (multiple-value-list (find-symbol "X" "COMMON-LISP-USER")) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (multiple-value-list (find-symbol "X" "COMMON-LISP-USER")) + #+END_SRC - #+BEGIN_SRC lisp :session pcl :exports both - (multiple-value-list (ignore-errors x)) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (multiple-value-list (ignore-errors x)) + #+END_SRC - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (multiple-value-list (find-symbol "X" "COMMON-LISP-USER")) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (multiple-value-list (find-symbol "X" "COMMON-LISP-USER")) + #+END_SRC - The function [[http://clhs.lisp.se/Body/f_find_s.htm][=find-symbol=]] is analogous to the function =find-package=: - given some /name/, a character string, it looks for a symbol with this name. - Remember the correspondence between packages and names? A similar - correspondence exists between symbols and names, but it's more involved. In - particular, a name is /never sufficient/ to determine a symbol, a - /package/ is also necessary. This is why the =find-symbol= function requires - /two/ arguments, the name of the symbol and the package with respect to - which the search is to be done. + The function [[http://clhs.lisp.se/Body/f_find_s.htm][=find-symbol=]] is analogous to the function =find-package=: + given some /name/, a character string, it looks for a symbol with this name. + Remember the correspondence between packages and names? A similar + correspondence exists between symbols and names, but it's more involved. In + particular, a name is /never sufficient/ to determine a symbol, a + /package/ is also necessary. This is why the =find-symbol= function requires + /two/ arguments, the name of the symbol and the package with respect to + which the search is to be done. - At the beginning of our story, no symbol with the name ="X"= existed in the - default package ="COMMON-LISP-USER"=, and the return value of =find-symbol= - is negative, =nil=. (We will explain the second =nil= value in a moment.) - Then we pass the Lisp reader the one character expression '=x='. Lisp - evaluates it according to its /read-eval-print/ cycle. First, Lisp - /reads/ the expression and notices that the symbol =x= is used. It examines - the current package ="COMMON-LISP-USER"=, and does /not/ find such a symbol. - Before doing anything else, Lisp /allocates/ (creates) this symbol, the - right terminology being: "Lisp /interns/ a symbol =x= of name ="X"= in the - package ="COMMON-LISP-USER"=." To refer to this symbol, the pair made of - /its/ name ="X"= and the (not /its/!!) package ="COMMON-LISP-USER"= are - necessary, but it would be cumbersome to have to write the expression - =(find-symbol "X" "COMMON-LISP-USER")= every time this symbol is used. To - simplify the process of referring to a symbol the designers of Lisp have - organized the workspace as follows: if a symbol is read, its character - string is capitalized, giving its /name/, and the default package is - assumed. In other words, the text ='x'= is roughly equivalent to the text - =(find-symbol "X" "COMMON-LISP-USER")=. How convenient! ('Roughly', because - '=x=' may trigger the allocation of a symbol. In contrast, =find-symbol= - never allocates a symbol; but see the function =intern= later.) In the - second expression of our example, once Lisp has "understood" that the user - intends to use the symbol =x=, and observing that such a symbol is not - present in the package ="COMMON-LISP-USER"=, it allocates a symbol of name - ="X"= and /interns/ it in the package ="COMMON-LISP-USER"=. More - specifically, a pointer referring to the just allocated symbol is added to - the list $InS(p)$ of the internal symbols of the package $p$. + At the beginning of our story, no symbol with the name ="X"= existed in the + default package ="COMMON-LISP-USER"=, and the return value of =find-symbol= + is negative, =nil=. (We will explain the second =nil= value in a moment.) + Then we pass the Lisp reader the one character expression '=x='. Lisp + evaluates it according to its /read-eval-print/ cycle. First, Lisp + /reads/ the expression and notices that the symbol =x= is used. It examines + the current package ="COMMON-LISP-USER"=, and does /not/ find such a symbol. + Before doing anything else, Lisp /allocates/ (creates) this symbol, the + right terminology being: "Lisp /interns/ a symbol =x= of name ="X"= in the + package ="COMMON-LISP-USER"=." To refer to this symbol, the pair made of + /its/ name ="X"= and the (not /its/!!) package ="COMMON-LISP-USER"= are + necessary, but it would be cumbersome to have to write the expression + =(find-symbol "X" "COMMON-LISP-USER")= every time this symbol is used. To + simplify the process of referring to a symbol the designers of Lisp have + organized the workspace as follows: if a symbol is read, its character + string is capitalized, giving its /name/, and the default package is + assumed. In other words, the text ='x'= is roughly equivalent to the text + =(find-symbol "X" "COMMON-LISP-USER")=. How convenient! ('Roughly', because + '=x=' may trigger the allocation of a symbol. In contrast, =find-symbol= + never allocates a symbol; but see the function =intern= later.) In the + second expression of our example, once Lisp has "understood" that the user + intends to use the symbol =x=, and observing that such a symbol is not + present in the package ="COMMON-LISP-USER"=, it allocates a symbol of name + ="X"= and /interns/ it in the package ="COMMON-LISP-USER"=. More + specifically, a pointer referring to the just allocated symbol is added to + the list $InS(p)$ of the internal symbols of the package $p$. - Note also that it is common in Lisp to input the symbols in lowercase - letters, and Lisp prints them in uppercase. This might be convenient for - distinguishing input from output in an interactive session, but requires - some clarification. In particular, there is no difference between the - symbols =nil= and =NIL=, whereas the strings ="nil"= and ="NIL"= are - different. + Note also that it is common in Lisp to input the symbols in lowercase + letters, and Lisp prints them in uppercase. This might be convenient for + distinguishing input from output in an interactive session, but requires + some clarification. In particular, there is no difference between the + symbols =nil= and =NIL=, whereas the strings ="nil"= and ="NIL"= are + different. - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (multiple-value-list (find-symbol "nil" "COMMON-LISP-USER")) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (multiple-value-list (find-symbol "nil" "COMMON-LISP-USER")) + #+END_SRC - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (multiple-value-list (find-symbol "NIL" "COMMON-LISP-USER")) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (multiple-value-list (find-symbol "NIL" "COMMON-LISP-USER")) + #+END_SRC - The fruitless search for a /symbol/ with the lower-case name ="nil"= (a - /string/) returns a double negative answer, but it is the second =NIL= that - is meaningful! Compare that with the second expression which has the same - first return value, but a different second one. The symbol =NIL= also plays - in Lisp the role of the boolean /false/, which creates an ambiguity: if the - answer is the symbol =NIL= is that a negative answer or is it a positive - answer made of the symbol =NIL=? The ambiguity is resolved by the /second/ - return value. In the first case, the second =NIL= /confirms/ that the first - =NIL= is to be interpreted as the boolean /false/. In the second expression, - the second return value =:INHERITED=, not a negative, indicates that the - symbol =NIL= has been found, and that its /accessibility/ via the package - ="COMMON-LISP-USER"= is /inherited/, a point to be explained later. In other - words, the function =find-symbol= returns a genuine symbol /and/ its - accessibility via the package argument, or a pair of =nil='s if no symbol is - found. The logician can deduce that an accessibility cannot be the symbol - =nil=! + The fruitless search for a /symbol/ with the lower-case name ="nil"= (a + /string/) returns a double negative answer, but it is the second =NIL= that + is meaningful! Compare that with the second expression which has the same + first return value, but a different second one. The symbol =NIL= also plays + in Lisp the role of the boolean /false/, which creates an ambiguity: if the + answer is the symbol =NIL= is that a negative answer or is it a positive + answer made of the symbol =NIL=? The ambiguity is resolved by the /second/ + return value. In the first case, the second =NIL= /confirms/ that the first + =NIL= is to be interpreted as the boolean /false/. In the second expression, + the second return value =:INHERITED=, not a negative, indicates that the + symbol =NIL= has been found, and that its /accessibility/ via the package + ="COMMON-LISP-USER"= is /inherited/, a point to be explained later. In other + words, the function =find-symbol= returns a genuine symbol /and/ its + accessibility via the package argument, or a pair of =nil='s if no symbol is + found. The logician can deduce that an accessibility cannot be the symbol + =nil=! - Let us return to the one character expression '=x='. The read part of the - read-eval-print loop cycle reads the symbol =x= and interns it in the - package ="COMMON-LISP-USER"=. The expression is /read/ and must now be - /evaluated/. The evaluation of a symbol consists in looking for a /value/ - of this symbol. To this end a value pointer in the symbol's internal - representation is examined. In this case it is found that, at this time, - there is no value for the freshly allocated symbol =x=. Therefore the /eval/ - step of the /read-eval-print/ cycle generates an error, terminating the - cycle with an informative error message. In any case, a symbol of name - ="X"= is now present in the package ="COMMON-LISP-USER"=, as confirmed by - the value of the last expression. The symbol's accessibility via the - ="COMMON-LISP-USER"= package is /internal/, which is to be explained later. + Let us return to the one character expression '=x='. The read part of the + read-eval-print loop cycle reads the symbol =x= and interns it in the + package ="COMMON-LISP-USER"=. The expression is /read/ and must now be + /evaluated/. The evaluation of a symbol consists in looking for a /value/ + of this symbol. To this end a value pointer in the symbol's internal + representation is examined. In this case it is found that, at this time, + there is no value for the freshly allocated symbol =x=. Therefore the /eval/ + step of the /read-eval-print/ cycle generates an error, terminating the + cycle with an informative error message. In any case, a symbol of name + ="X"= is now present in the package ="COMMON-LISP-USER"=, as confirmed by + the value of the last expression. The symbol's accessibility via the + ="COMMON-LISP-USER"= package is /internal/, which is to be explained later. -** Examining a symbol. +* Examining a symbol. - A symbol is a Lisp object with a rich internal structure and there are - several functions for exploring symbols and their properties. Let us - examine in detail the symbol =x= allocated in the previous section. + A symbol is a Lisp object with a rich internal structure and there are + several functions for exploring symbols and their properties. Let us + examine in detail the symbol =x= allocated in the previous section. - #+BEGIN_SRC lisp :session pcl :exports both - (symbol-name 'x) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (symbol-name 'x) + #+END_SRC - The [[http://clhs.lisp.se/Body/f_symb_2.htm][=symbol-name=]] function returns the /name/ of a symbol; it is analogous - to the =package-name= function for a package. The Lisp function - =symbol-name= is crucial for our subject, and we denote it as a mathematical - function $sn: Sm \longrightarrow St$, a function which in general is not - injective: several symbols may have the same name, this is our main subject. + The [[http://clhs.lisp.se/Body/f_symb_2.htm][=symbol-name=]] function returns the /name/ of a symbol; it is analogous + to the =package-name= function for a package. The Lisp function + =symbol-name= is crucial for our subject, and we denote it as a mathematical + function $sn: Sm \longrightarrow St$, a function which in general is not + injective: several symbols may have the same name, this is our main subject. - Note that in the previous expression the symbol =x= has been quoted ='x= to - prevent its evaluation. More precisely, ='x= is an abbreviation for the - expression =(quote x)=, where [[http://clhs.lisp.se/Body/s_quote.htm][=quote=]] is a /special/ function which /does - not/ evaluate its argument, and it returns this argument as is. Hence, the - previous expression is equivalent to: + Note that in the previous expression the symbol =x= has been quoted ='x= to + prevent its evaluation. More precisely, ='x= is an abbreviation for the + expression =(quote x)=, where [[http://clhs.lisp.se/Body/s_quote.htm][=quote=]] is a /special/ function which /does + not/ evaluate its argument, and it returns this argument as is. Hence, the + previous expression is equivalent to: - #+BEGIN_SRC lisp :session pcl :exports both - (symbol-name (quote x)) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (symbol-name (quote x)) + #+END_SRC - Here, the non-quoted =x= does not generate an error. If instead you do not - quote the symbol =x= (implicitly via ='=, or explicitly via =quote=) it will - be evaluated before being used and generate an error: + Here, the non-quoted =x= does not generate an error. If instead you do not + quote the symbol =x= (implicitly via ='=, or explicitly via =quote=) it will + be evaluated before being used and generate an error: - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (multiple-value-list (ignore-errors (symbol-name x))) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (multiple-value-list + (ignore-errors + (symbol-name x))) + #+END_SRC - The package which /owns/ a symbol, its /home package/, can be determined - with the function [[http://clhs.lisp.se/Body/f_symb_3.htm][=symbol-package=]]. + The package which /owns/ a symbol, its /home package/, can be determined + with the function [[http://clhs.lisp.se/Body/f_symb_3.htm][=symbol-package=]]. - #+BEGIN_SRC lisp :session pcl :exports both - (symbol-package 'x) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (symbol-package 'x) + #+END_SRC - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (multiple-value-list (find-symbol "X" "COMMON-LISP-USER")) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (multiple-value-list (find-symbol "X" "COMMON-LISP-USER")) + #+END_SRC - As we have just seen, a symbol produces a name and a package (with the help - of =symbol-name= and =symbol-package=). Conversely, given a name and a - package, =find-symbol= produces the symbol with this name /via/ this - package. The reader might think that there is a correspondence between - symbols and pairs of strings and packages: - $$Sm \longleftrightarrow St\times P$$ - However, the situation is more involved: for the beginner, this might be a - convenient point of view, but in fact such a point of view is wrong. If you - intend to fully understand the complex relationship between strings, - packages and symbols, please forget this tempting but terribly misleading - correspondence. The goal of the next sections is to establish the correct - point of view. For completeness we finish this section with a brief glance - at the other data possibly stored in a symbol. A symbol can have a value. - You may remember that in our Lisp session the symbol =x= does not (yet) have - a value. This can be established by the predicate [[http://clhs.lisp.se/Body/f_boundp.htm][=boundp=]]: + As we have just seen, a symbol produces a name and a package (with the help + of =symbol-name= and =symbol-package=). Conversely, given a name and a + package, =find-symbol= produces the symbol with this name /via/ this + package. The reader might think that there is a correspondence between + symbols and pairs of strings and packages: + $$Sm \longleftrightarrow St\times P$$ + However, the situation is more involved: for the beginner, this might be a + convenient point of view, but in fact such a point of view is wrong. If you + intend to fully understand the complex relationship between strings, + packages and symbols, please forget this tempting but terribly misleading + correspondence. The goal of the next sections is to establish the correct + point of view. For completeness we finish this section with a brief glance + at the other data possibly stored in a symbol. A symbol can have a value. + You may remember that in our Lisp session the symbol =x= does not (yet) have + a value. This can be established by the predicate [[http://clhs.lisp.se/Body/f_boundp.htm][=boundp=]]: - #+BEGIN_SRC lisp :session pcl :exports both - (boundp 'x) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (boundp 'x) + #+END_SRC - The main method to give a symbol a value is the [[http://clhs.lisp.se/Body/m_setf_.htm][=setf=]] function (a macro). - In most Common Lisp implementations, the =setf= macro may be used directly, - in which case the default status of the argument symbol is /variable/. In - strict ANSI implementations such as SBCL here, a =defvar= statement is - required to explicitly define this status. Other possible statuses are - /constant/ (via =defconstant=) and /parameter/ (via =defparameter=). + The main method to give a symbol a value is the [[http://clhs.lisp.se/Body/m_setf_.htm][=setf=]] function (a macro). + In most Common Lisp implementations, the =setf= macro may be used directly, + in which case the default status of the argument symbol is /variable/. In + strict ANSI implementations such as SBCL here, a =defvar= statement is + required to explicitly define this status. Other possible statuses are + /constant/ (via =defconstant=) and /parameter/ (via =defparameter=). - #+BEGIN_SRC lisp :session pcl :exports both - (defvar x) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (defvar x) + #+END_SRC - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (setf x '(4 5 6)) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (setf x '(4 5 6)) + #+END_SRC - #+BEGIN_SRC lisp :session pcl :exports both - (boundp 'x) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (boundp 'x) + #+END_SRC - Note that the first argument of =setf=, the symbol =x=, is not evaluated. - Otherwise an error would be generated, since the symbol =x= does not yet - have a value. After the =(setf ...)= expression has been evaluated, the - symbol =x= does have a value, in this case, the list =(4 5 6)=. This value - would now be the result of the evaluation of the expression =x=. It can also - be obtained with the function [[http://clhs.lisp.se/Body/f_symb_5.htm][=symbol-value=]]. (In this tutorial, we do not - study the possible difference between, on the one hand, the simple - /evaluation/ of the symbol =x= asked for by the expression ='x'= and the - /evaluation/ of =(symbol-value 'x)= on the other. In our elementary examples - there is no difference between the two. Possible differences might come from - different variable scopes, such as /lexical/ or /dynamic/, but this subject - is not studied here.) + Note that the first argument of =setf=, the symbol =x=, is not evaluated. + Otherwise an error would be generated, since the symbol =x= does not yet + have a value. After the =(setf ...)= expression has been evaluated, the + symbol =x= does have a value, in this case, the list =(4 5 6)=. This value + would now be the result of the evaluation of the expression =x=. It can also + be obtained with the function [[http://clhs.lisp.se/Body/f_symb_5.htm][=symbol-value=]]. (In this tutorial, we do not + study the possible difference between, on the one hand, the simple + /evaluation/ of the symbol =x= asked for by the expression ='x'= and the + /evaluation/ of =(symbol-value 'x)= on the other. In our elementary examples + there is no difference between the two. Possible differences might come from + different variable scopes, such as /lexical/ or /dynamic/, but this subject + is not studied here.) - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - x - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + x + #+END_SRC - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (symbol-value 'x) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (symbol-value 'x) + #+END_SRC - Don't forget to quote the symbol! See the following error: + Don't forget to quote the symbol! See the following error: - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (multiple-value-list (ignore-errors (symbol-value x))) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (multiple-value-list + (ignore-errors + (symbol-value x))) + #+END_SRC - A symbol can also have a /functional value/. This does not mean that the - value we just discussed could be a function (which it could be!). It means - that /besides/ the previous value, a symbol can also have an /additional/ - value, a function, which can be used independently of the "ordinary" value - of this symbol. For example the function $n \mapsto 10−n$ could be recorded - as the /functional/ value of the same symbol, and this function could then - be used as shown below. + A symbol can also have a /functional value/. This does not mean that the + value we just discussed could be a function (which it could be!). It means + that /besides/ the previous value, a symbol can also have an /additional/ + value, a function, which can be used independently of the "ordinary" value + of this symbol. For example the function $n \mapsto 10 - n$ could be recorded + as the /functional/ value of the same symbol, and this function could then + be used as shown below. - #+BEGIN_SRC lisp :session pcl :exports both - (defun x (n) (- 10 n)) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (defun x (n) (- 10 n)) + #+END_SRC - #+BEGIN_SRC lisp :session pcl :exports both - (x 3) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (x 3) + #+END_SRC - Both values coexist in the symbol without any interference: + Both values coexist in the symbol without any interference: - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (symbol-value 'x) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (symbol-value 'x) + #+END_SRC - #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim - (symbol-function 'x) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (symbol-function 'x) + #+END_SRC - and can be used jointly and independently: + and can be used jointly and independently: - #+BEGIN_SRC lisp :session pcl :exports both - (x (first x)) - #+END_SRC + #+BEGIN_SRC lisp :session pcl :exports both + (x (first x)) + #+END_SRC - You might already suspect that the position of =x= just after a left - parenthesis =(x ...)= makes Lisp extract the /functional/ value and not the - "ordinary" value. This is correct, but not the subject of this tutorial. - Finally, we mention only in passing the following: + You might already suspect that the position of =x= just after a left + parenthesis =(x ...)= makes Lisp extract the /functional/ value and not the + "ordinary" value. This is correct, but not the subject of this tutorial. + Finally, we mention only in passing the following: - 1. A symbol can have a functional value while not having an ordinary value. - 2. An ordinary value can be a functional object, usually then called via - =funcall= or =apply=. - 3. A symbol also contains a property list or =plist=, with many possible - uses, but not at all studied here. + 1. A symbol can have a functional value while not having an ordinary value. + 2. An ordinary value can be a functional object, usually then called via + =funcall= or =apply=. + 3. A symbol also contains a property list or =plist=, with many possible + uses, but not at all studied here. - The internal structure of the [[http://clhs.lisp.se/Body/t_symbol.htm#symbol][symbol]] =x= might be visualized thus: + The internal structure of the [[http://clhs.lisp.se/Body/t_symbol.htm#symbol][symbol]] =x= might be visualized thus: - #+BEGIN_EXAMPLE - +-----------------+ - | Name o-|-----> "x" - +-----------------+ - | Value o-|-----> (4 5 6) - +-----------------+ - | Function o-|-----> (lambda (n) (- 10 n)) - +-----------------+ - | Package o-|-----> # - + ----------------+ - | Property list o-|-----> NIL - +-----------------+ - #+END_EXAMPLE + #+BEGIN_EXAMPLE + +-----------------+ + | Name o-|-----> "x" + +-----------------+ + | Value o-|-----> (4 5 6) + +-----------------+ + | Function o-|-----> (lambda (n) (- 10 n)) + +-----------------+ + | Package o-|-----> # + + ----------------+ + | Property list o-|-----> NIL + +-----------------+ + #+END_EXAMPLE -** But what the hell is a package? +* But what the hell is a package? - Now we attack the heart of our subject.\\ + Now we attack the heart of our subject.\\ - **Fact 1:** A package $p\in P$ maintains four fundamental lists: + **Fact 1:** A package $p\in P$ maintains four fundamental lists: - - A list $InS(p)$ of its internal symbols. - - A list $ExS(p)$ of its external symbols. - - A list $ShgS(p)$ of its shadowing symbols. - - A list $U(p)$ of its used packages. + - A list $InS(p)$ of its internal symbols. + - A list $ExS(p)$ of its external symbols. + - A list $ShgS(p)$ of its shadowing symbols. + - A list $U(p)$ of its used packages.\\ + + The first important fact toward understanding the subject is this: the first + three lists are lists of /symbols/ or, more precisely, lists of pointers + (machine addresses) aimed at the symbols. Every symbol has a /unique/ + "existence": a symbol is a unique machine object in the environment, but + /several/ packages may /see/ the same symbol, that is, include the machine + address of this symbol. In particular these lists are not lists of symbol + names (strings). There is another mechanism that allows Lisp to reach a + symbol given its name. Every symbol can be accessed directly via a suitable + package, and several packages can in general play this role for the same + symbol at a given moment in a Lisp session. For example, all the + [[http://clhs.lisp.se/Front/X_Symbol.htm][standard Lisp symbols]] in the ="COMMON-LISP"= package typically are + accessible via any package. + + No duplicate symbol (more precisely, no duplicate pointer) is to be found in + each of these lists. Also the relations $InS(p)\cap ExS(p)=\emptyset$ and + $ShgS(p)\subset InS(p)\cup ExS(p)$ must be satisfied, for reasons to be + studied later.\\ + + **Fact 2:** Given the current set of packages, assumed /coherent/, and given + the current state of all the fundamental lists of these packages, the + function =find-symbol= can unambiguously determine /whether/ a symbol of a + given name (some string) is /accessible/ via some package; if so, this + symbol is unique.\\ + + The importance of the package argument of =find-symbol= could make the + reader believe the function =symbol-package= will be useful for various + tests. This is not the case: All this function returns is the "birth place" + of the symbol, technically called its /home package/, which says almost + nothing about the current status of this symbol with respect to any package. + All it says is that at least it is /interned/ in this package. In + particular, a symbol can be accessible via several packages, possibly + different from its home package. Here is a simple illustration: + + #+BEGIN_SRC lisp :session pcl :exports both + (symbol-package 'nil) + #+END_SRC + + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (multiple-value-list (find-symbol "NIL" "COMMON-LISP")) + #+END_SRC + + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (multiple-value-list (find-symbol "NIL" "COMMON-LISP-USER")) + #+END_SRC + + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (eq (find-symbol "NIL" "COMMON-LISP") + (find-symbol "NIL" "COMMON-LISP-USER")) + #+END_SRC + + The /home package/ of =nil= is ="COMMON-LISP"=, and this symbol of name + ="NIL"= is accessible via ="COMMON-LISP"=, but also via + ="COMMON-LISP-USER"=, though not with the same status. It is /external/ in + the first case and /inherited/ in the second case, points to be examined + later. The value (=T=) of the last expression /proves/ that both symbols, + determined by =find-symbol= via different packages, in fact are the same. + Fact 2 can be made a little more precise: At any given time during a Lisp + session, a set $P$ of packages and a set $Sm$ of symbols are defined. The + various lists of symbols $InS(p)$, $ExS(p)$ and $ShgS(p)$, and the list + $U(p)$ of packages used by a package $p\in P$ together define without any + ambiguity which symbols are accessible via the package $p$. In other words, + there is a well defined function $\rho$: + $$ + \rho: P \longrightarrow [St \longrightarrow Sm \cup \{\mathtt{nil}\}] + $$ + We chose the letter $\rho$ for reader, because this function is mainly used + by the reader. Our "mathematical" function $\rho$ is nothing but an avatar + of the Lisp function =find-symbol=. Let $p\in P$ be a package and + $st\in St$ be a string. Then: + $$ + \rho(p)(st) = (\mathtt{find-symbol}\; st\; p) + $$ + The left-hand side uses the standard mathematical functional notation, and + the right-hand one uses the Lisp notation. If no symbol is found for a pair + $(st, p)$, the symbol (!) =nil= is returned and the second value of + =find-symbol=, the symbol =nil= again, tells the user that the symbol search + did not return anything. A package $p$ is nothing but a way of defining the + function $\rho(p):St\longrightarrow Sm\cup\{\mathtt{nil}\}$. In other words, + the four fundamental lists of a package determine what character strings + appear as the names of the symbols accessible via this package. + This approach is described in detail now. + +* Internal symbols. + + The first fundamental list of a package is the list of its /internal + symbols/. It is a pity that no standard Lisp function can produce this list, + but here is a simple solution to the problem: + + #+BEGIN_SRC lisp :session pcl :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 + + We can list now all the internal symbols of a package: + + #+BEGIN_SRC lisp :session pcl :exports both :results value verbatim + (package-internal-symbols "COMMON-LISP-USER") + #+END_SRC + + In fact, only the first ten internal symbols are displayed. We see in + particular the symbols =package-internal-symbols=, =s= and =rslt= used in + the definition of our function. Some are rather esoteric, strictly speaking + illegal: at the beginning of a Lisp session, the ="COMMON-LISP-USER"= + package should in principle be void of symbols. To make our experiments more + 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.