emacs.d/clones/lisp/www.cs.cmu.edu/Groups/AI/html/cltl/clm/node120.html

506 lines
20 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
<!Converted with LaTeX2HTML 0.6.5 (Tue Nov 15 1994) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds >
<HEAD>
<TITLE>11.9. An Example</TITLE>
</HEAD>
<BODY>
<meta name="description" value=" An Example">
<meta name="keywords" value="clm">
<meta name="resource-type" value="document">
<meta name="distribution" value="global">
<P>
<b>Common Lisp the Language, 2nd Edition</b>
<BR> <HR><A NAME=tex2html3017 HREF="node121.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html3015 HREF="node111.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html3011 HREF="node119.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html3019 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html3020 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
<B> Next:</B> <A NAME=tex2html3018 HREF="node121.html"> Numbers</A>
<B>Up:</B> <A NAME=tex2html3016 HREF="node111.html"> Packages</A>
<B> Previous:</B> <A NAME=tex2html3012 HREF="node119.html"> Modules</A>
<HR> <P>
<H1><A NAME=SECTION001590000000000000000>11.9. An Example</A></H1>
<P>
<img align=bottom alt="old_change_begin" src="gif/old_change_begin.gif"><br>
<A NAME=PACKAGEEXAMPLESECTION>Most</A>
users will want to load and use packages but will never need to
build one. Often a user will load a number of packages into the
<tt>user</tt> package whenever using Common Lisp. Typically an implementation
might provide some sort of initialization file mechanism to make such setup
automatic when the Lisp starts up. Table <A HREF="node120.html#INITFILETABLE">11-1</A>
shows such an initialization file, one that simply
causes other facilities to be loaded.
<br><img align=bottom alt="old_change_end" src="gif/old_change_end.gif">
<P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
X3J13 voted in March 1989 (LISP-PACKAGE-NAME) <A NAME=11142>&#160;</A> to specify that
the forthcoming ANSI Common Lisp will use the package name <tt>common-lisp-user</tt>
instead of <tt>user</tt>.
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
<A NAME=INITFILETABLE>&#160;</A>
<listing>
----------------------------------------------------------------
Table 11-1: An Initialization File
;;;; Lisp init file for I. Newton.
;;; Set up the USER package the way I like it.
(require 'calculus) ;I use CALCULUS a lot; load it.
(use-package 'calculus) ;Get easy access to its
; exported symbols.
(require 'newtonian-mechanics) ;Same thing for NEWTONIAN-MECHANICS
(use-package 'newtonian-mechanics)
;;; I just want a few things from RELATIVITY,
;;; and other things conflict.
;;; Import only what I need into the USER package.
(require 'relativity)
(import '(relativity:speed-of-light
relativity:ignore-small-errors))
;;; These are worth loading, but I will use qualified names,
;;; such as PHLOGISTON:MAKE-FIRE-BOTTLE, to get at any symbols
;;; I might need from these packages.
(require 'phlogiston)
(require 'alchemy)
;;; End of Lisp init file for I. Newton.
----------------------------------------------------------------
</listing>
<P>
When each of two files uses some symbols from the other, the author
of those files must be
careful to arrange the contents of the file in the proper order.
Typically each file contains a single package that is a complete module.
The contents of such a file should include the following items, in
order:
<P>
<OL><LI>
A call to <tt>provide</tt> that announces the module name.
<P>
<LI>
A call to <tt>in-package</tt> that establishes the package.
<P>
<LI>
A call to <tt>shadow</tt> that establishes any local symbols that will shadow
symbols that would otherwise be inherited from packages that this
package will use.
<P>
<LI>
A call to <tt>export</tt> that establishes all of this package's external
symbols.
<P>
<LI>
Any number of calls to <tt>require</tt> to load other modules that the
contents of this file might want to use or refer to. (Because the
calls to <tt>require</tt> follow the calls to <tt>in-package</tt>,
<tt>shadow</tt>, and <tt>export</tt>, it is possible for the packages that may
be loaded to refer to external symbols in this package.)
<P>
<LI>
Any number of calls to <tt>use-package</tt>, to make external
symbols from other packages accessible in this package.
<P>
<LI>
Any number of calls to <tt>import</tt>, to make
symbols from other packages present in this package.
<P>
<LI>
Finally, the definitions making up the contents of this package/module.
</OL>
<P>
The following mnemonic sentence may be helpful in remembering
the proper order of these calls:<br>
<blockquote>
<b>Put in seven extremely random user interface commands.</b>
</blockquote>
<P>
Each word of the sentence corresponds to one item in the above ordering:
<PRE>
Put <tt>Provide</tt>
IN <tt>IN-package</tt>
Seven <tt>Shadow</tt>
EXtremely <tt>EXport</tt>
Random <tt>Require</tt>
USEr <tt>USE-package</tt>
Interface <tt>Import</tt>
COmmands COntents of package/module
</PRE>
<P>
The sentence says what it helps you to do.
<P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
The most distressing aspect of the X3J13 vote to eliminate
<tt>provide</tt> and <tt>require</tt>
(REQUIRE-PATHNAME-DEFAULTS) <A NAME=11192>&#160;</A>
is of course that it completely ruins the mnemonic sentence.
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
Now, suppose for the sake of example
that the <tt>phlogiston</tt> and <tt>alchemy</tt> packages are
single-file, single-package modules as described above. The <tt>phlogiston</tt>
package needs to use the <tt>alchemy</tt> package, and the <tt>alchemy</tt> package
needs to use several
external symbols from the <tt>phlogiston</tt> package.
The definitions in the <tt>alchemy</tt> and <tt>phlogiston</tt> files
(see tables <A HREF="node120.html#ALCHEMYFILETABLE">11-2</A> and <A HREF="node120.html#PHLOGISTONFILETABLE">11-3</A>)
allow a
user to specify <tt>require</tt> statements for either of these modules, or for
both of them in either order, and all relevant information will be
loaded automatically and in the correct order.
<P>
<A NAME=ALCHEMYFILETABLE>&#160;</A>
<listing>
----------------------------------------------------------------
Table 11-2: File alchemy
;;;; Alchemy functions, written and maintained by Merlin, Inc.
(provide 'alchemy) ;The module is named ALCHEMY.
(in-package 'alchemy) ;So is the package.
;;; There is nothing to shadow.
;;; Here is the external interface.
(export '(lead-to-gold gold-to-lead
antimony-to-zinc elixir-of-life))
;;; This package/module needs a function from
;;; the PHLOGISTON package/module.
(require 'phlogiston)
;;; We don't frequently need most of the external symbols from
;;; PHLOGISTON, so it's not worth doing a USE-PACKAGE on it.
;;; We'll just use qualified names as needed. But we use
;;; one function, MAKE-FIRE-BOTTLE, a lot, so import it.
;;; It's external in PHLOGISTON and so can be referred to
;;; here using ":" qualified-name syntax.
(import '(phlogiston:make-fire-bottle))
;;; Now for the real contents of this file.
(defun lead-to-gold (x)
"Takes a quantity of lead and returns gold."
(when (> (phlogiston:heat-flow 5 x x) ;Using a qualified symbol
3)
(make-fire-bottle x)) ;Using an imported symbol
(gild x))
;;; And so on ...
----------------------------------------------------------------
</listing>
<P>
<A NAME=PHLOGISTONFILETABLE>&#160;</A>
<listing>
----------------------------------------------------------------
Table 11-3: File phlogiston
;;;; Phlogiston functions, by Thermofluidics, Ltd.
(provide 'phlogiston) ;The module is named PHLOGISTON.
(in-package 'phlogiston) ;So is the package.
;;; There is nothing to shadow.
;;; Here is the external interface.
(export '(heat-flow cold-flow mix-fluids separate-fluids
burn make-fire-bottle))
;;; This file uses functions from the ALCHEMY package/module.
(require 'alchemy)
;;; We use alchemy functions a lot, so use the package.
;;; This will allow symbols exported from the ALCHEMY package
;;; to be referred to here without the need for qualified names.
(use-package 'alchemy)
;;; No calls to IMPORT are needed here.
;;; The real contents of this package/module.
(defvar *feeling-weak* nil)
(defun heat-flow (amount x y)
"Make some amount of heat flow from x to y."
(when *feeling-weak*
(quaff (elixir-of-life))) ;No qualifier is needed.
(push-heat amount x y))
;;; And so on ...
----------------------------------------------------------------
</listing>
<p>
<img align=bottom alt="old_change_begin" src="gif/old_change_begin.gif"><br>
For very large modules whose contents are spread over several files
(the <tt>lisp</tt> package is an example), it is recommended that the user
create the package and declare all of the shadows and external symbols
in a separate file, so that this can be loaded before anything that
might use symbols from this package.
<br><img align=bottom alt="old_change_end" src="gif/old_change_end.gif">
<P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
Indeed, the <tt>defpackage</tt> macro
approved by X3J13 in January 1989
(DEFPACKAGE) <A NAME=11210>&#160;</A>
encourages the use of such a separate file.
(By the way,
X3J13 voted in March 1989 (LISP-PACKAGE-NAME) <A NAME=11211>&#160;</A> to specify that
the forthcoming ANSI Common Lisp will use the package name <tt>common-lisp</tt>
instead of <tt>lisp</tt>.)
Let's take a look at a revision
of I. Newton's files using <tt>defpackage</tt>.
<P>
The new version of the initialization file avoids using <tt>require</tt>;
instead, we assume that <tt>load</tt> will do the job
(see table <A HREF="node120.html#DEFPACKAGEINITFILETABLE">11-4</A>).
<P>
<A NAME=DEFPACKAGEINITFILETABLE>&#160;</A>
<listing>
----------------------------------------------------------------
Table 11-4: An Initialization File When defpackage Is Used
;;;; Lisp init file for I. Newton.
;;; Set up the USER package the way I like it.
(load "calculus") ;I use CALCULUS a lot; load it.
(use-package 'calculus) ;Get easy access to its
; exported symbols.
(load "newtonian-mechanics") ;Ditto for NEWTONIAN-MECHANICS
(use-package 'newtonian-mechanics)
;;; I just want a few things from RELATIVITY,
;;; and other things conflict.
;;; Import only what I need into the USER package.
(load "relativity")
(import '(relativity:speed-of-light
relativity:ignore-small-errors))
;;; These are worth loading, but I will use qualified names,
;;; such as PHLOGISTON:MAKE-FIRE-BOTTLE, to get at any symbols
;;; I might need from these packages.
(load "phlogiston")
(load "alchemy")
;;; End of Lisp init file for I. Newton.
----------------------------------------------------------------
</listing>
<P>
The other files have each been split into two parts, one that
establishes the package and one that defines the contents.
This example uses a simple convention that for any file
named, say, ``<tt>foo</tt>'' the file named ``<tt>foo-package</tt>''
contains the necessary <tt>defpackage</tt> and/or other package-establishing
code. The idiom
<P><pre>
(unless (find-package &quot;FOO&quot;)
(load &quot;foo-package&quot;))
</pre><P>
is conventionally used to load a package definition but only if the package
has not already been defined. (This is a bit clumsy, and there are other
ways to arrange things so that a package is defined no more than once.)
<P>
The file <tt>alchemy-package</tt> is shown in
table <A HREF="node120.html#DEFPACKAGEALCHEMYPACKAGETABLE">11-5</A>.
The tricky point here is that the <tt>alchemy</tt> and <tt>phlogiston</tt>
packages contain mutual references (each imports from the other),
and so <tt>defpackage</tt> alone cannot do the job. Therefore
the <tt>phlogiston</tt> package is not mentioned in a <tt>:use</tt> option
in the <tt>defpackage</tt> for the <tt>alchemy</tt> package. Instead,
the function <tt>use-package</tt> is called explicitly, after the package definition
for <tt>phlogiston</tt> has been loaded. Note that this file has
been coded with excruciating care so as to operate correctly even if
the package current when the file is loaded does not inherit from
the <tt>common-lisp</tt> package. In particular, the standard load-package-definition
idiom has been peppered with package qualifiers:
<P><pre>
(cl:unless (cl:find-package &quot;PHLOGISTON&quot;)
(cl:load &quot;phlogiston-package&quot;))
</pre><P>
Note the use of the nickname <tt>cl</tt> for the <tt>common-lisp</tt> package.
<P>
The <tt>alchemy</tt> file, shown in table <A HREF="node120.html#DEFPACKAGEALCHEMYFILETABLE">11-6</A>,
simply loads the <tt>alchemy</tt> package definition,
makes that package current, and then defines the ``real contents''
of the package.
<P>
<A NAME=DEFPACKAGEALCHEMYFILETABLE>&#160;</A>
<listing>
----------------------------------------------------------------
Table 11-5: File alchemy-package Using defpackage
;;;; Alchemy package, written and maintained by Merlin, Inc.
(cl:defpackage "ALCHEMY"
(:export "LEAD-TO-GOLD" "GOLD-TO-LEAD"
"ANTIMONY-TO-ZINC" "ELIXIR-OF-LIFE")
)
;;; This package needs a function from the PHLOGISTON package.
;;; Load the definition of the PHLOGISTON package if necessary.
(cl:unless (cl:find-package "PHLOGISTON")
(cl:load "phlogiston-package"))
;;; We don't frequently need most of the external symbols from
;;; PHLOGISTON, so it's not worth doing a USE-PACKAGE on it.
;;; We'll just use qualified names as needed. But we use
;;; one function, MAKE-FIRE-BOTTLE, a lot, so import it.
;;; It's external in PHLOGISTON and so can be referred to
;;; here using ":" qualified-name syntax.
(cl:import '(phlogiston:make-fire-bottle))
----------------------------------------------------------------
</listing>
<A NAME=DEFPACKAGEALCHEMYPACKAGETABLE>&#160;</A>
<listing>
----------------------------------------------------------------
Table 11-6: File alchemy Using defpackage
;;;; Alchemy functions, written and maintained by Merlin, Inc.
(unless (find-package "ALCHEMY")
(load "alchemy-package"))
(in-package 'alchemy)
(defun lead-to-gold (x)
"Takes a quantity of lead and returns gold."
(when (> (phlogiston:heat-flow 5 x x) ;Using a qualified symbol
3)
(make-fire-bottle x)) ;Using an imported symbol
(gild x))
;;; And so on ...
----------------------------------------------------------------
</listing>
<P>
The file <tt>phlogiston-package</tt> is shown in
table <A HREF="node120.html#DEFPACKAGEPHLOGISTONPACKAGETABLE">11-7</A>.
This one is a little more straightforward than the file <tt>alchemy-package</tt>,
because the latter bears the responsibility for breaking the
circular package references.
This file simply makes sure that the <tt>alchemy</tt> package is defined
and then performs a <tt>defpackage</tt> for the <tt>phlogiston</tt> package.
<P>
<A NAME=DEFPACKAGEPHLOGISTONPACKAGETABLE>&#160;</A>
<listing>
----------------------------------------------------------------
Table 11-7: File phlogiston-package Using defpackage
;;;; Phlogiston package definition, by Thermofluidics, Ltd.
;;; This package uses functions from the ALCHEMY package.
(cl:unless (cl:find-package "ALCHEMY")
(cl:load "alchemy-package"))
(cl:defpackage "PHLOGISTON"
(:use "COMMON-LISP" "ALCHEMY")
(:export "HEAT-FLOW"
"COLD-FLOW"
"MIX-FLUIDS"
"SEPARATE-FLUIDS"
"BURN"
"MAKE-FIRE-BOTTLE")
)
----------------------------------------------------------------
</listing>
<P>
The <tt>phlogiston</tt> file, shown in table <A HREF="node120.html#DEFPACKAGEPHLOGISTONFILETABLE">11-8</A>,
simply loads the <tt>phlogiston</tt> package definition,
makes that package current, and then defines the ``real contents''
of the package.
<P>
<A NAME=DEFPACKAGEPHLOGISTONFILETABLE>&#160;</A>
<listing>
----------------------------------------------------------------
Table 11-8: File phlogiston Using defpackage
;;;; Phlogiston functions, by Thermofluidics, Ltd.
(unless (find-package "PHLOGISTON")
(load "phlogiston-package"))
(in-package 'phlogiston)
(defvar *feeling-weak* nil)
(defun heat-flow (amount x y)
"Make some amount of heat flow from x to y."
(when *feeling-weak*
(quaff (elixir-of-life))) ;No qualifier is needed.
(push-heat amount x y))
;;; And so on ...
----------------------------------------------------------------
</listing>
<P>
Let's look at the question of package circularity in
this example a little more closely.
Suppose that the file <tt>alchemy-package</tt> is loaded first.
It defines the <tt>alchemy</tt> package and then loads
file <tt>phlogiston-package</tt>. That file in turn finds that the
package <tt>alchemy</tt> has already been defined and therefore does
not attempt to load file <tt>alchemy-package</tt> again; it merely
defines package <tt>phlogiston</tt>. The file <tt>alchemy-package</tt>
then has a chance to import <tt>phlogiston:make-fire-bottle</tt> and everything
is fine.
<P>
On the other hand, suppose that the file <tt>phlogiston-package</tt> is
loaded first. It finds that the
package <tt>alchemy</tt> has <i>not</i> already been defined, and therefore
it immediately loads file <tt>alchemy-package</tt>.
That file in turn defines the <tt>alchemy</tt> package; then it
finds that package <tt>phlogiston</tt> is not yet defined and so
loads file <tt>phlogiston-package</tt> <i>again</i> (indeed, in nested fashion).
This time file <tt>phlogiston-package</tt> <i>does</i> find that the
package <tt>alchemy</tt> has already been defined, so it simply defines
package <tt>phlogiston</tt> and terminates.
The file <tt>alchemy-package</tt> then imports <tt>phlogiston:make-fire-bottle</tt>
and terminates.
Finally, the outer loading of file <tt>phlogiston-package</tt>
<i>re-defines</i> package <tt>phlogiston</tt>. Oh, dear. Fortunately the
two definitions of package <tt>phlogiston</tt> agree in every detail, so
everything ought to be all right. Still, it looks a bit dicey; <i>I</i>
certainly don't have the same warm, fuzzy feeling that I would if
no package were defined more than once.
<P>
Conclusion: <tt>defpackage</tt> goes a long way, but it certainly doesn't
solve all the possible problems of package and file management.
Neither did <tt>require</tt> and <tt>provide</tt>. Perhaps further experimentation
will yield facilities appropriate for future standardization.
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
<BR> <HR><A NAME=tex2html3017 HREF="node121.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html3015 HREF="node111.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html3011 HREF="node119.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html3019 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html3020 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
<B> Next:</B> <A NAME=tex2html3018 HREF="node121.html"> Numbers</A>
<B>Up:</B> <A NAME=tex2html3016 HREF="node111.html"> Packages</A>
<B> Previous:</B> <A NAME=tex2html3012 HREF="node119.html"> Modules</A>
<HR> <P>
<HR>
<P><ADDRESS>
AI.Repository@cs.cmu.edu
</ADDRESS>
</BODY>