In this chapter, you'll learn how to find your way around Common Lisp without resorting so often to the manuals. (You do read the fine manuals, don't you?)
Oh, there's one thing you should keep in mind while you're reading this chapter: all of these tools work equally well for the built-in functionality of your Lisp system and for all of the Lisp programs that you write.
Common Lisp defines 978 symbols. Whatever implementation you use probably defines hundreds of additional symbols for language extensions, additional libraries, a graphical user interface, etc. Are you going to remember the names of all these symbols? Not likely...
What you can do is to remember part of the name. This is
pretty easy, because the language and library designers have a
limited memory (just like you and me) and they tend to name related
objects with similar names. So, most of the mapping functions (see
Chapter 12) will have
in their names, the GUI library will probably have
WINDOW in the names of all the functions, macros, and
variables having something to do with windows, and so on.
Once you have a good guess at a part of a name, you can find
all of the matching names by using a very handy tool named
? (apropos "MAP" :cl) MAP, Def: FUNCTION MAP-INTO, Def: FUNCTION MAPC, Def: FUNCTION MAPCAN, Def: FUNCTION MAPCAR, Def: FUNCTION MAPCON, Def: FUNCTION MAPHASH, Def: FUNCTION MAPL, Def: FUNCTION MAPLIST, Def: FUNCTION
APROPOS expects a string or a symbol -- this
provides the fragment of the name that you'd like to find. An
optional second argument designates a package; use it if you'd like
to limit your search to the symbols in a particular package. The
package designator can be a string or symbol matching the name or
nickname of a package (see Chapter 3,
Lesson 10), or it can be the package object itself. If you omit
the package designator, then
APROPOS will search for
symbols in all packages.
Your Lisp implementation may produce output that looks somewhat different from that shown here. Generally, you'll see the symbol names listed with a very brief description of the global object named by the symbol.
Here's an example of the output from
APROPOS on my
Lisp system when I search without a package designator:
? (apropos "SEQUENCE") TOOLS::BROWSER-SEQUENCE-TABLE CCL::CHECK-SEQUENCE-BOUNDS, Def: FUNCTION ITERATE::CHECK-SEQUENCE-KEYWORDS, Def: FUNCTION TOOLS::CLASS-BROWSER-SEQUENCE-TABLE ITERATE::CLAUSE-FOR-IN-SEQUENCE-0, Def: FUNCTION ITERATE::CLAUSE-FOR-INDEX-OF-SEQUENCE-0, Def: FUNCTION CCL::CONSED-SEQUENCE ; many lines omitted STREAM-READ-SEQUENCE, Def: STANDARD-GENERIC-FUNCTION STREAM-WRITE-SEQUENCE, Def: STANDARD-GENERIC-FUNCTION DEFSYSTEM::SYSTEMS-SEQUENCE-DIALOG-ITEM TAB-SEQUENCE-ITEM TABLE-SEQUENCE, Def: STANDARD-GENERIC-FUNCTION :TABLE-SEQUENCE, Value: :TABLE-SEQUENCE SETF::|CCL::TABLE-SEQUENCE|, Def: STANDARD-GENERIC-FUNCTION WRITE-SEQUENCE, Def: FUNCTION
Notice that most of the symbols are prefixed with a package name, since they are not imported into the current (COMMON-LISP-USER) package. Again, your Lisp implementation may produce somewhat different results, but it should show you a list of symbols with package prefixes, plus whatever other information the designers of your implementation thought would be helpful yet concise.
In these examples, I've used uppercase strings as arguments to
APROPOS. Some implementations perform a case-sensitive
match, while others ignore case. Symbol names are case sensitive in
Lisp, but the Lisp reader translates symbols to uppercase by
default. So if you specify an uppercase name to
you'll find most -- perhaps all -- of the matching names; you'll
miss only those that were intentionally interned using lower case
letters. And if your
APROPOS ignores case, you'll get
all of the matches, regardless of case.
You could also supply a symbol to
APROPOS. The only
disadvantage of this is that these partial symbols pollute the
namespace of the current package. The storage requirement is
trivial, but you'll have to be aware that
find these partial symbols in future matches, and you'll have to
ignore these to find the symbols you'd really like to see.
Once you know the name of a symbol, you can get additional information
by using the
DESCRIBE function. As with
the output of
DESCRIBE varies among Lisp implementations.
Here's an example generated using my Lisp system:
; Describe a symbol ? (describe 'length) Symbol: LENGTH Function EXTERNAL in package: #<Package "COMMON-LISP"> Print name: "LENGTH" Value: #<Unbound> Function: #<Compiled-function LENGTH #x34C39B6> Arglist: (SEQUENCE) Plist: (:ANSI-CL-URL "fun_length.html") ; Describe a string ? (describe "LENGTH") "LENGTH" Type: (SIMPLE-BASE-STRING 6) Class: #<BUILT-IN-CLASS SIMPLE-BASE-STRING> Length: 6 0: #\L 1: #\E 2: #\N 3: #\G 4: #\T 5: #\H ; Describe a function ? (describe #'length) #<Compiled-function LENGTH #x34C39B6> Name: LENGTH Arglist (declaration): (SEQUENCE)
This example used three different argument types: a symbol, a
string, and a function. These are all correct, but you get what you
ask for. These all have their uses, but you will generally want to
supply a symbol argument to
DESCRIBE, because it tends
to produce the most information.
INSPECT is like
DESCRIBE, but instead
of printing the information it presents the information in some kind
of interactive display; typically either a command loop in the
current listener or a new window with its own user interface. You
should experiment with
INSPECT on your own Lisp system
to learn how it behaves.
INSPECT is very handy for exploring complex nested
data structures, since you can "drill down" to just the information
that interests you at the moment. Most
specialized viewers for certain types of data, such as functions and
CLOS objects. Many implementations of
allow you to edit the data being inspected.
Sometimes, you need to know more about a variable than you
can discover with
INSPECT. And for functions, you
really need the programmer's description (unless you're willing to
read assembly language code, see Chapter
16 if you have these urges). The
function gives you access to the programmer's innermost thoughts (or
at least what she was willing to write in a documentation string).
DOCUMENTATION function expects two arguments.
The first is an object for which you wish to retrieve documentation,
or a symbol naming that object. The second is a symbol designating
the kind of documentation (there are several) you wish to retrieve.
The interface described above is the one required by the ANSI Common Lisp specification. Some implementations still support an interface which predates the ANSI specification -- these expect a symbol for both arguments. We'll use that convention in our examples, since it works in both ANSI and pre-ANSI implementations.
Several Lisp constructs let you provide an optional documentation
string. The following table shows the second
DOCUMENTATION argument (first line of each pair)
together with the Lisp constructs for which documentation strings
defmacro, special forms
The list above works in both ANSI and pre-ANSI Lisp implementations. The following list shows the documentation types which have been added for ANSI implementations.
Here are some examples:
? (documentation 'length 'function) "returns the number of elements in sequence." ? (defun a-function-with-docstring () "This function always returns T." t) A-FUNCTION-WITH-DOCSTRING ? (documentation 'a-function-with-docstring 'function) "This function always returns T."
If you specify a symbol for which there is no documentation, or a
documentation type which does not select documentation defined for
the symbol, then
DOCUMENTATION will return
A Lisp implementation is permitted to discard documentation
strings. If documentation strings from your own program are not
accessible via the
DOCUMENTATION function, consult your
implementation's manual to find out whether there's a way to retain
documentation strings (there usually is). If documentation strings
are missing from Common Lisp functions or from vendor supplied
libraries, consult your vendor.