annotate man/lispref/control.texi @ 622:11502791fc1c

[xemacs-hg @ 2001-06-22 01:49:57 by ben] dired-msw.c: Fix problem noted by Michael Sperber with directories containing [] and code that destructively modifies an existing string. term\AT386.el: Fix warnings. term\apollo.el: Removed. Kill kill kill. Sync with FSF and remove most crap. term\linux.el: Removed. Sync with FSF. Don't define most defns, because they are automatically defined by termcap. But do add defns for keys that normally get defined as f13, f14, etc. and really ought to be shift-f3, shift-f4, etc. (NOTE: I did this based on Cygwin, which emulates the Linux console. I would appreciate it if someone on Linux could verify.) term\cygwin.el: New. Load term/linux. term\lk201.el, term\news.el, term\vt100.el: Sync with FSF. Fix warnings. dialog-gtk.el: Fix warning. For 21.4: help.el, update-elc.el: Compile in proper order. Maybe for 21.4: keydefs.el: Add a defn for M-?, previously undefined, to access help -- in case the terminal is not set up right, or f1 gets redefined. README: Rewrite.
author ben
date Fri, 22 Jun 2001 01:50:04 +0000
parents 576fb035e263
children 37e56e920ac5
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1 @c -*-texinfo-*-
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
2 @c This is part of the XEmacs Lisp Reference Manual.
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
3 @c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
4 @c See the file lispref.texi for copying conditions.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
5 @setfilename ../../info/control.info
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
6 @node Control Structures, Variables, Evaluation, Top
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
7 @chapter Control Structures
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
8 @cindex special forms for control structures
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
9 @cindex control structures
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
10
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
11 A Lisp program consists of expressions or @dfn{forms} (@pxref{Forms}).
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
12 We control the order of execution of the forms by enclosing them in
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
13 @dfn{control structures}. Control structures are special forms which
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
14 control when, whether, or how many times to execute the forms they
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
15 contain.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
16
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
17 The simplest order of execution is sequential execution: first form
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
18 @var{a}, then form @var{b}, and so on. This is what happens when you
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
19 write several forms in succession in the body of a function, or at top
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
20 level in a file of Lisp code---the forms are executed in the order
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
21 written. We call this @dfn{textual order}. For example, if a function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
22 body consists of two forms @var{a} and @var{b}, evaluation of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
23 function evaluates first @var{a} and then @var{b}, and the function's
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
24 value is the value of @var{b}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
25
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
26 Explicit control structures make possible an order of execution other
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
27 than sequential.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
28
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
29 XEmacs Lisp provides several kinds of control structure, including
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
30 other varieties of sequencing, conditionals, iteration, and (controlled)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
31 jumps---all discussed below. The built-in control structures are
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
32 special forms since their subforms are not necessarily evaluated or not
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
33 evaluated sequentially. You can use macros to define your own control
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
34 structure constructs (@pxref{Macros}).
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
35
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
36 @menu
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
37 * Sequencing:: Evaluation in textual order.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
38 * Conditionals:: @code{if}, @code{cond}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
39 * Combining Conditions:: @code{and}, @code{or}, @code{not}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
40 * Iteration:: @code{while} loops.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
41 * Nonlocal Exits:: Jumping out of a sequence.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
42 @end menu
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
43
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
44 @node Sequencing
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
45 @section Sequencing
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
46
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
47 Evaluating forms in the order they appear is the most common way
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
48 control passes from one form to another. In some contexts, such as in a
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
49 function body, this happens automatically. Elsewhere you must use a
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
50 control structure construct to do this: @code{progn}, the simplest
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
51 control construct of Lisp.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
52
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
53 A @code{progn} special form looks like this:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
54
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
55 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
56 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
57 (progn @var{a} @var{b} @var{c} @dots{})
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
58 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
59 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
60
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
61 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
62 and it says to execute the forms @var{a}, @var{b}, @var{c} and so on, in
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
63 that order. These forms are called the body of the @code{progn} form.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
64 The value of the last form in the body becomes the value of the entire
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
65 @code{progn}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
66
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
67 @cindex implicit @code{progn}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
68 In the early days of Lisp, @code{progn} was the only way to execute
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
69 two or more forms in succession and use the value of the last of them.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
70 But programmers found they often needed to use a @code{progn} in the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
71 body of a function, where (at that time) only one form was allowed. So
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
72 the body of a function was made into an ``implicit @code{progn}'':
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
73 several forms are allowed just as in the body of an actual @code{progn}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
74 Many other control structures likewise contain an implicit @code{progn}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
75 As a result, @code{progn} is not used as often as it used to be. It is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
76 needed now most often inside an @code{unwind-protect}, @code{and},
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
77 @code{or}, or in the @var{then}-part of an @code{if}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
78
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
79 @defspec progn forms@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
80 This special form evaluates all of the @var{forms}, in textual
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
81 order, returning the result of the final form.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
82
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
83 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
84 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
85 (progn (print "The first form")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
86 (print "The second form")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
87 (print "The third form"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
88 @print{} "The first form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
89 @print{} "The second form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
90 @print{} "The third form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
91 @result{} "The third form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
92 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
93 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
94 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
95
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
96 Two other control constructs likewise evaluate a series of forms but return
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
97 a different value:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
98
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
99 @defspec prog1 form1 forms@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
100 This special form evaluates @var{form1} and all of the @var{forms}, in
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
101 textual order, returning the result of @var{form1}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
102
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
103 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
104 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
105 (prog1 (print "The first form")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
106 (print "The second form")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
107 (print "The third form"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
108 @print{} "The first form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
109 @print{} "The second form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
110 @print{} "The third form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
111 @result{} "The first form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
112 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
113 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
114
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
115 Here is a way to remove the first element from a list in the variable
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
116 @code{x}, then return the value of that former element:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
117
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
118 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
119 (prog1 (car x) (setq x (cdr x)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
120 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
121 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
122
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
123 @defspec prog2 form1 form2 forms@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
124 This special form evaluates @var{form1}, @var{form2}, and all of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
125 following @var{forms}, in textual order, returning the result of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
126 @var{form2}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
127
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
128 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
129 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
130 (prog2 (print "The first form")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
131 (print "The second form")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
132 (print "The third form"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
133 @print{} "The first form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
134 @print{} "The second form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
135 @print{} "The third form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
136 @result{} "The second form"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
137 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
138 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
139 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
140
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
141 @node Conditionals
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
142 @section Conditionals
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
143 @cindex conditional evaluation
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
144
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
145 Conditional control structures choose among alternatives. XEmacs Lisp
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
146 has two conditional forms: @code{if}, which is much the same as in other
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
147 languages, and @code{cond}, which is a generalized case statement.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
148
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
149 @defspec if condition then-form else-forms@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
150 @code{if} chooses between the @var{then-form} and the @var{else-forms}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
151 based on the value of @var{condition}. If the evaluated @var{condition} is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
152 non-@code{nil}, @var{then-form} is evaluated and the result returned.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
153 Otherwise, the @var{else-forms} are evaluated in textual order, and the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
154 value of the last one is returned. (The @var{else} part of @code{if} is
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
155 an example of an implicit @code{progn}. @xref{Sequencing}.)
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
156
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
157 If @var{condition} has the value @code{nil}, and no @var{else-forms} are
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
158 given, @code{if} returns @code{nil}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
159
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
160 @code{if} is a special form because the branch that is not selected is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
161 never evaluated---it is ignored. Thus, in the example below,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
162 @code{true} is not printed because @code{print} is never called.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
163
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
164 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
165 @group
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
166 (if nil
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
167 (print 'true)
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
168 'very-false)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
169 @result{} very-false
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
170 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
171 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
172 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
173
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
174 @defspec cond clause@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
175 @code{cond} chooses among an arbitrary number of alternatives. Each
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
176 @var{clause} in the @code{cond} must be a list. The @sc{car} of this
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
177 list is the @var{condition}; the remaining elements, if any, the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
178 @var{body-forms}. Thus, a clause looks like this:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
179
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
180 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
181 (@var{condition} @var{body-forms}@dots{})
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
182 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
183
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
184 @code{cond} tries the clauses in textual order, by evaluating the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
185 @var{condition} of each clause. If the value of @var{condition} is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
186 non-@code{nil}, the clause ``succeeds''; then @code{cond} evaluates its
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
187 @var{body-forms}, and the value of the last of @var{body-forms} becomes
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
188 the value of the @code{cond}. The remaining clauses are ignored.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
189
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
190 If the value of @var{condition} is @code{nil}, the clause ``fails'', so
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
191 the @code{cond} moves on to the following clause, trying its
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
192 @var{condition}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
193
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
194 If every @var{condition} evaluates to @code{nil}, so that every clause
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
195 fails, @code{cond} returns @code{nil}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
196
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
197 A clause may also look like this:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
198
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
199 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
200 (@var{condition})
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
201 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
202
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
203 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
204 Then, if @var{condition} is non-@code{nil} when tested, the value of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
205 @var{condition} becomes the value of the @code{cond} form.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
206
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
207 The following example has four clauses, which test for the cases where
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
208 the value of @code{x} is a number, string, buffer and symbol,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
209 respectively:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
210
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
211 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
212 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
213 (cond ((numberp x) x)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
214 ((stringp x) x)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
215 ((bufferp x)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
216 (setq temporary-hack x) ; @r{multiple body-forms}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
217 (buffer-name x)) ; @r{in one clause}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
218 ((symbolp x) (symbol-value x)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
219 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
220 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
221
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
222 Often we want to execute the last clause whenever none of the previous
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
223 clauses was successful. To do this, we use @code{t} as the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
224 @var{condition} of the last clause, like this: @code{(t
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
225 @var{body-forms})}. The form @code{t} evaluates to @code{t}, which is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
226 never @code{nil}, so this clause never fails, provided the @code{cond}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
227 gets to it at all.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
228
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
229 For example,
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
230
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
231 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
232 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
233 (cond ((eq a 'hack) 'foo)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
234 (t "default"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
235 @result{} "default"
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
236 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
237 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
238
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
239 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
240 This expression is a @code{cond} which returns @code{foo} if the value
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
241 of @code{a} is 1, and returns the string @code{"default"} otherwise.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
242 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
243
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
244 Any conditional construct can be expressed with @code{cond} or with
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
245 @code{if}. Therefore, the choice between them is a matter of style.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
246 For example:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
247
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
248 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
249 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
250 (if @var{a} @var{b} @var{c})
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
251 @equiv{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
252 (cond (@var{a} @var{b}) (t @var{c}))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
253 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
254 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
255
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
256 @node Combining Conditions
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
257 @section Constructs for Combining Conditions
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
258
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
259 This section describes three constructs that are often used together
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
260 with @code{if} and @code{cond} to express complicated conditions. The
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
261 constructs @code{and} and @code{or} can also be used individually as
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
262 kinds of multiple conditional constructs.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
263
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
264 @defun not condition
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
265 This function tests for the falsehood of @var{condition}. It returns
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
266 @code{t} if @var{condition} is @code{nil}, and @code{nil} otherwise.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
267 The function @code{not} is identical to @code{null}, and we recommend
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
268 using the name @code{null} if you are testing for an empty list.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
269 @end defun
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
270
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
271 @defspec and conditions@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
272 The @code{and} special form tests whether all the @var{conditions} are
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
273 true. It works by evaluating the @var{conditions} one by one in the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
274 order written.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
275
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
276 If any of the @var{conditions} evaluates to @code{nil}, then the result
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
277 of the @code{and} must be @code{nil} regardless of the remaining
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
278 @var{conditions}; so @code{and} returns right away, ignoring the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
279 remaining @var{conditions}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
280
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
281 If all the @var{conditions} turn out non-@code{nil}, then the value of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
282 the last of them becomes the value of the @code{and} form.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
283
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
284 Here is an example. The first condition returns the integer 1, which is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
285 not @code{nil}. Similarly, the second condition returns the integer 2,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
286 which is not @code{nil}. The third condition is @code{nil}, so the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
287 remaining condition is never evaluated.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
288
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
289 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
290 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
291 (and (print 1) (print 2) nil (print 3))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
292 @print{} 1
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
293 @print{} 2
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
294 @result{} nil
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
295 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
296 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
297
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
298 Here is a more realistic example of using @code{and}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
299
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
300 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
301 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
302 (if (and (consp foo) (eq (car foo) 'x))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
303 (message "foo is a list starting with x"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
304 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
305 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
306
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
307 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
308 Note that @code{(car foo)} is not executed if @code{(consp foo)} returns
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
309 @code{nil}, thus avoiding an error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
310
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
311 @code{and} can be expressed in terms of either @code{if} or @code{cond}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
312 For example:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
313
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
314 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
315 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
316 (and @var{arg1} @var{arg2} @var{arg3})
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
317 @equiv{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
318 (if @var{arg1} (if @var{arg2} @var{arg3}))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
319 @equiv{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
320 (cond (@var{arg1} (cond (@var{arg2} @var{arg3}))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
321 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
322 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
323 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
324
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
325 @defspec or conditions@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
326 The @code{or} special form tests whether at least one of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
327 @var{conditions} is true. It works by evaluating all the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
328 @var{conditions} one by one in the order written.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
329
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
330 If any of the @var{conditions} evaluates to a non-@code{nil} value, then
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
331 the result of the @code{or} must be non-@code{nil}; so @code{or} returns
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
332 right away, ignoring the remaining @var{conditions}. The value it
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
333 returns is the non-@code{nil} value of the condition just evaluated.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
334
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
335 If all the @var{conditions} turn out @code{nil}, then the @code{or}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
336 expression returns @code{nil}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
337
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
338 For example, this expression tests whether @code{x} is either 0 or
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
339 @code{nil}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
340
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
341 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
342 (or (eq x nil) (eq x 0))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
343 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
344
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
345 Like the @code{and} construct, @code{or} can be written in terms of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
346 @code{cond}. For example:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
347
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
348 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
349 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
350 (or @var{arg1} @var{arg2} @var{arg3})
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
351 @equiv{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
352 (cond (@var{arg1})
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
353 (@var{arg2})
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
354 (@var{arg3}))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
355 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
356 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
357
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
358 You could almost write @code{or} in terms of @code{if}, but not quite:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
359
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
360 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
361 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
362 (if @var{arg1} @var{arg1}
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
363 (if @var{arg2} @var{arg2}
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
364 @var{arg3}))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
365 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
366 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
367
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
368 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
369 This is not completely equivalent because it can evaluate @var{arg1} or
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
370 @var{arg2} twice. By contrast, @code{(or @var{arg1} @var{arg2}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
371 @var{arg3})} never evaluates any argument more than once.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
372 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
373
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
374 @node Iteration
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
375 @section Iteration
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
376 @cindex iteration
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
377 @cindex recursion
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
378
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
379 Iteration means executing part of a program repetitively. For
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
380 example, you might want to repeat some computation once for each element
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
381 of a list, or once for each integer from 0 to @var{n}. You can do this
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
382 in XEmacs Lisp with the special form @code{while}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
383
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
384 @defspec while condition forms@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
385 @code{while} first evaluates @var{condition}. If the result is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
386 non-@code{nil}, it evaluates @var{forms} in textual order. Then it
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
387 reevaluates @var{condition}, and if the result is non-@code{nil}, it
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
388 evaluates @var{forms} again. This process repeats until @var{condition}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
389 evaluates to @code{nil}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
390
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
391 There is no limit on the number of iterations that may occur. The loop
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
392 will continue until either @var{condition} evaluates to @code{nil} or
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
393 until an error or @code{throw} jumps out of it (@pxref{Nonlocal Exits}).
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
394
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
395 The value of a @code{while} form is always @code{nil}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
396
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
397 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
398 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
399 (setq num 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
400 @result{} 0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
401 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
402 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
403 (while (< num 4)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
404 (princ (format "Iteration %d." num))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
405 (setq num (1+ num)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
406 @print{} Iteration 0.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
407 @print{} Iteration 1.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
408 @print{} Iteration 2.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
409 @print{} Iteration 3.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
410 @result{} nil
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
411 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
412 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
413
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
414 If you would like to execute something on each iteration before the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
415 end-test, put it together with the end-test in a @code{progn} as the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
416 first argument of @code{while}, as shown here:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
417
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
418 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
419 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
420 (while (progn
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
421 (forward-line 1)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
422 (not (looking-at "^$"))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
423 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
424 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
425
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
426 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
427 This moves forward one line and continues moving by lines until it
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
428 reaches an empty. It is unusual in that the @code{while} has no body,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
429 just the end test (which also does the real work of moving point).
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
430 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
431
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
432 @node Nonlocal Exits
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
433 @section Nonlocal Exits
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
434 @cindex nonlocal exits
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
435
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
436 A @dfn{nonlocal exit} is a transfer of control from one point in a
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
437 program to another remote point. Nonlocal exits can occur in XEmacs Lisp
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
438 as a result of errors; you can also use them under explicit control.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
439 Nonlocal exits unbind all variable bindings made by the constructs being
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
440 exited.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
441
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
442 @menu
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
443 * Catch and Throw:: Nonlocal exits for the program's own purposes.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
444 * Examples of Catch:: Showing how such nonlocal exits can be written.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
445 * Errors:: How errors are signaled and handled.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
446 * Cleanups:: Arranging to run a cleanup form if an error happens.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
447 @end menu
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
448
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
449 @node Catch and Throw
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
450 @subsection Explicit Nonlocal Exits: @code{catch} and @code{throw}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
451
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
452 Most control constructs affect only the flow of control within the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
453 construct itself. The function @code{throw} is the exception to this
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
454 rule of normal program execution: it performs a nonlocal exit on
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
455 request. (There are other exceptions, but they are for error handling
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
456 only.) @code{throw} is used inside a @code{catch}, and jumps back to
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
457 that @code{catch}. For example:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
458
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
459 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
460 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
461 (catch 'foo
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
462 (progn
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
463 @dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
464 (throw 'foo t)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
465 @dots{}))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
466 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
467 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
468
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
469 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
470 The @code{throw} transfers control straight back to the corresponding
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
471 @code{catch}, which returns immediately. The code following the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
472 @code{throw} is not executed. The second argument of @code{throw} is used
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
473 as the return value of the @code{catch}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
474
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
475 The @code{throw} and the @code{catch} are matched through the first
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
476 argument: @code{throw} searches for a @code{catch} whose first argument
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
477 is @code{eq} to the one specified. Thus, in the above example, the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
478 @code{throw} specifies @code{foo}, and the @code{catch} specifies the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
479 same symbol, so that @code{catch} is applicable. If there is more than
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
480 one applicable @code{catch}, the innermost one takes precedence.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
481
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
482 Executing @code{throw} exits all Lisp constructs up to the matching
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
483 @code{catch}, including function calls. When binding constructs such as
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
484 @code{let} or function calls are exited in this way, the bindings are
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
485 unbound, just as they are when these constructs exit normally
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
486 (@pxref{Local Variables}). Likewise, @code{throw} restores the buffer
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
487 and position saved by @code{save-excursion} (@pxref{Excursions}), and
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
488 the narrowing status saved by @code{save-restriction} and the window
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
489 selection saved by @code{save-window-excursion} (@pxref{Window
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
490 Configurations}). It also runs any cleanups established with the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
491 @code{unwind-protect} special form when it exits that form
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
492 (@pxref{Cleanups}).
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
493
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
494 The @code{throw} need not appear lexically within the @code{catch}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
495 that it jumps to. It can equally well be called from another function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
496 called within the @code{catch}. As long as the @code{throw} takes place
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
497 chronologically after entry to the @code{catch}, and chronologically
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
498 before exit from it, it has access to that @code{catch}. This is why
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
499 @code{throw} can be used in commands such as @code{exit-recursive-edit}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
500 that throw back to the editor command loop (@pxref{Recursive Editing}).
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
501
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
502 @cindex CL note---only @code{throw} in Emacs
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
503 @quotation
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
504 @b{Common Lisp note:} Most other versions of Lisp, including Common Lisp,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
505 have several ways of transferring control nonsequentially: @code{return},
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
506 @code{return-from}, and @code{go}, for example. XEmacs Lisp has only
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
507 @code{throw}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
508 @end quotation
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
509
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
510 @defspec catch tag body@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
511 @cindex tag on run time stack
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
512 @code{catch} establishes a return point for the @code{throw} function. The
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
513 return point is distinguished from other such return points by @var{tag},
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
514 which may be any Lisp object. The argument @var{tag} is evaluated normally
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
515 before the return point is established.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
516
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
517 With the return point in effect, @code{catch} evaluates the forms of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
518 @var{body} in textual order. If the forms execute normally, without
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
519 error or nonlocal exit, the value of the last body form is returned from
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
520 the @code{catch}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
521
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
522 If a @code{throw} is done within @var{body} specifying the same value
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
523 @var{tag}, the @code{catch} exits immediately; the value it returns is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
524 whatever was specified as the second argument of @code{throw}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
525 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
526
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
527 @defun throw tag value
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
528 The purpose of @code{throw} is to return from a return point previously
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
529 established with @code{catch}. The argument @var{tag} is used to choose
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
530 among the various existing return points; it must be @code{eq} to the value
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
531 specified in the @code{catch}. If multiple return points match @var{tag},
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
532 the innermost one is used.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
533
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
534 The argument @var{value} is used as the value to return from that
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
535 @code{catch}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
536
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
537 @kindex no-catch
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
538 If no return point is in effect with tag @var{tag}, then a @code{no-catch}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
539 error is signaled with data @code{(@var{tag} @var{value})}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
540 @end defun
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
541
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
542 @node Examples of Catch
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
543 @subsection Examples of @code{catch} and @code{throw}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
544
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
545 One way to use @code{catch} and @code{throw} is to exit from a doubly
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
546 nested loop. (In most languages, this would be done with a ``go to''.)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
547 Here we compute @code{(foo @var{i} @var{j})} for @var{i} and @var{j}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
548 varying from 0 to 9:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
549
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
550 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
551 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
552 (defun search-foo ()
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
553 (catch 'loop
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
554 (let ((i 0))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
555 (while (< i 10)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
556 (let ((j 0))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
557 (while (< j 10)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
558 (if (foo i j)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
559 (throw 'loop (list i j)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
560 (setq j (1+ j))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
561 (setq i (1+ i))))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
562 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
563 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
564
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
565 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
566 If @code{foo} ever returns non-@code{nil}, we stop immediately and return a
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
567 list of @var{i} and @var{j}. If @code{foo} always returns @code{nil}, the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
568 @code{catch} returns normally, and the value is @code{nil}, since that
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
569 is the result of the @code{while}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
570
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
571 Here are two tricky examples, slightly different, showing two
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
572 return points at once. First, two return points with the same tag,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
573 @code{hack}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
574
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
575 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
576 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
577 (defun catch2 (tag)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
578 (catch tag
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
579 (throw 'hack 'yes)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
580 @result{} catch2
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
581 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
582
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
583 @group
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
584 (catch 'hack
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
585 (print (catch2 'hack))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
586 'no)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
587 @print{} yes
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
588 @result{} no
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
589 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
590 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
591
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
592 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
593 Since both return points have tags that match the @code{throw}, it goes to
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
594 the inner one, the one established in @code{catch2}. Therefore,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
595 @code{catch2} returns normally with value @code{yes}, and this value is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
596 printed. Finally the second body form in the outer @code{catch}, which is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
597 @code{'no}, is evaluated and returned from the outer @code{catch}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
598
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
599 Now let's change the argument given to @code{catch2}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
600
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
601 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
602 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
603 (defun catch2 (tag)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
604 (catch tag
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
605 (throw 'hack 'yes)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
606 @result{} catch2
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
607 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
608
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
609 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
610 (catch 'hack
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
611 (print (catch2 'quux))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
612 'no)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
613 @result{} yes
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
614 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
615 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
616
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
617 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
618 We still have two return points, but this time only the outer one has
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
619 the tag @code{hack}; the inner one has the tag @code{quux} instead.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
620 Therefore, @code{throw} makes the outer @code{catch} return the value
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
621 @code{yes}. The function @code{print} is never called, and the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
622 body-form @code{'no} is never evaluated.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
623
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
624 @node Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
625 @subsection Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
626 @cindex errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
627
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
628 When XEmacs Lisp attempts to evaluate a form that, for some reason,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
629 cannot be evaluated, it @dfn{signals} an @dfn{error}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
630
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
631 When an error is signaled, XEmacs's default reaction is to print an
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
632 error message and terminate execution of the current command. This is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
633 the right thing to do in most cases, such as if you type @kbd{C-f} at
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
634 the end of the buffer.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
635
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
636 In complicated programs, simple termination may not be what you want.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
637 For example, the program may have made temporary changes in data
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
638 structures, or created temporary buffers that should be deleted before
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
639 the program is finished. In such cases, you would use
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
640 @code{unwind-protect} to establish @dfn{cleanup expressions} to be
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
641 evaluated in case of error. (@xref{Cleanups}.) Occasionally, you may
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
642 wish the program to continue execution despite an error in a subroutine.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
643 In these cases, you would use @code{condition-case} to establish
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
644 @dfn{error handlers} to recover control in case of error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
645
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
646 Resist the temptation to use error handling to transfer control from
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
647 one part of the program to another; use @code{catch} and @code{throw}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
648 instead. @xref{Catch and Throw}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
649
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
650 @menu
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
651 * Signaling Errors:: How to report an error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
652 * Processing of Errors:: What XEmacs does when you report an error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
653 * Handling Errors:: How you can trap errors and continue execution.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
654 * Error Symbols:: How errors are classified for trapping them.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
655 @end menu
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
656
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
657 @node Signaling Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
658 @subsubsection How to Signal an Error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
659 @cindex signaling errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
660
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
661 Most errors are signaled ``automatically'' within Lisp primitives
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
662 which you call for other purposes, such as if you try to take the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
663 @sc{car} of an integer or move forward a character at the end of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
664 buffer; you can also signal errors explicitly with the functions
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
665 @code{error}, @code{signal}, and others.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
666
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
667 Quitting, which happens when the user types @kbd{C-g}, is not
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
668 considered an error, but it is handled almost like an error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
669 @xref{Quitting}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
670
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
671 XEmacs has a rich hierarchy of error symbols predefined via @code{deferror}.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
672
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
673 @example
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
674 error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
675 syntax-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
676 invalid-read-syntax
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
677 list-formation-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
678 malformed-list
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
679 malformed-property-list
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
680 circular-list
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
681 circular-property-list
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
682
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
683 invalid-argument
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
684 wrong-type-argument
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
685 args-out-of-range
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
686 wrong-number-of-arguments
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
687 invalid-function
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
688 no-catch
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
689
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
690 invalid-state
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
691 void-function
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
692 cyclic-function-indirection
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
693 void-variable
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
694 cyclic-variable-indirection
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
695
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
696 invalid-operation
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
697 invalid-change
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
698 setting-constant
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
699 editing-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
700 beginning-of-buffer
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
701 end-of-buffer
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
702 buffer-read-only
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
703 io-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
704 end-of-file
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
705 arith-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
706 range-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
707 domain-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
708 singularity-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
709 overflow-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
710 underflow-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
711 @end example
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
712
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
713 The five most common errors you will probably use or base your new
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
714 errors off of are @code{syntax-error}, @code{invalid-argument},
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
715 @code{invalid-state}, @code{invalid-operation}, and
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
716 @code{invalid-change}. Note the semantic differences:
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
717
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
718 @itemize @bullet
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
719 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
720 @code{syntax-error} is for errors in complex structures: parsed strings,
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
721 lists, and the like.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
722
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
723 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
724 @code{invalid-argument} is for errors in a simple value. Typically, the
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
725 entire value, not just one part of it, is wrong.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
726
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
727 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
728 @code{invalid-state} means that some settings have been changed in such
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
729 a way that their current state is unallowable. More and more, code is
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
730 being written more carefully, and catches the error when the settings
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
731 are being changed, rather than afterwards. This leads us to the next
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
732 error:
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
733
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
734 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
735 @code{invalid-change} means that an attempt is being made to change some
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
736 settings into an invalid state. @code{invalid-change} is a type of
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
737 @code{invalid-operation}.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
738
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
739 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
740 @code{invalid-operation} refers to all cases where code is trying to do
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
741 something that's disallowed. This includes file errors, buffer errors
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
742 (e.g. running off the end of a buffer), @code{invalid-change} as just
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
743 mentioned, and arithmetic errors.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
744 @end itemize
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
745
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
746 @defun error datum &rest args
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
747 This function signals a non-continuable error.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
748
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
749 @var{datum} should normally be an error symbol, i.e. a symbol defined
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
750 using @code{define-error}. @var{args} will be made into a list, and
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
751 @var{datum} and @var{args} passed as the two arguments to @code{signal},
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
752 the most basic error handling function.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
753
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
754 This error is not continuable: you cannot continue execution after the
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
755 error using the debugger @kbd{r} command. See also @code{cerror}.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
756
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
757 The correct semantics of @var{args} varies from error to error, but for
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
758 most errors that need to be generated in Lisp code, the first argument
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
759 should be a string describing the *context* of the error (i.e. the exact
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
760 operation being performed and what went wrong), and the remaining
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
761 arguments or \"frobs\" (most often, there is one) specify the offending
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
762 object(s) and/or provide additional details such as the exact error when
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
763 a file error occurred, e.g.:
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
764
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
765 @itemize @bullet
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
766 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
767 the buffer in which an editing error occurred.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
768 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
769 an invalid value that was encountered. (In such cases, the string
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
770 should describe the purpose or \"semantics\" of the value [e.g. if the
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
771 value is an argument to a function, the name of the argument; if the value
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
772 is the value corresponding to a keyword, the name of the keyword; if the
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
773 value is supposed to be a list length, say this and say what the purpose
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
774 of the list is; etc.] as well as specifying why the value is invalid, if
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
775 that's not self-evident.)
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
776 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
777 the file in which an error occurred. (In such cases, there should be a
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
778 second frob, probably a string, specifying the exact error that occurred.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
779 This does not occur in the string that precedes the first frob, because
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
780 that frob describes the exact operation that was happening.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
781 @end itemize
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
782
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
783 For historical compatibility, DATUM can also be a string. In this case,
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
784 @var{datum} and @var{args} are passed together as the arguments to
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
785 @code{format}, and then an error is signalled using the error symbol
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
786 @code{error} and formatted string. Although this usage of @code{error}
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
787 is very common, it is deprecated because it totally defeats the purpose
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
788 of having structured errors. There is now a rich set of defined errors
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
789 to use.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
790
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
791 See also @code{cerror}, @code{signal}, and @code{signal-error}."
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
792
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
793 These examples show typical uses of @code{error}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
794
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
795 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
796 @group
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
797 (error 'syntax-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
798 "Dialog descriptor must supply at least one button"
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
799 descriptor)
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
800 @end group
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
801
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
802 @group
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
803 (error "You have committed an error.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
804 Try something else.")
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
805 @error{} You have committed an error.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
806 Try something else.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
807 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
808
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
809 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
810 (error "You have committed %d errors." 10)
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
811 @error{} You have committed 10 errors.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
812 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
813 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
814
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
815 If you want to use your own string as an error message verbatim, don't
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
816 just write @code{(error @var{string})}. If @var{string} contains
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
817 @samp{%}, it will be interpreted as a format specifier, with undesirable
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
818 results. Instead, use @code{(error "%s" @var{string})}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
819 @end defun
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
820
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
821 @defun cerror datum &rest args
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
822 This function behaves like @code{error}, except that the error it
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
823 signals is continuable. That means that debugger commands @kbd{c} and
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
824 @kbd{r} can resume execution.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
825 @end defun
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
826
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
827 @defun signal error-symbol data
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
828 This function signals a continuable error named by @var{error-symbol}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
829 The argument @var{data} is a list of additional Lisp objects relevant to
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
830 the circumstances of the error.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
831
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
832 The argument @var{error-symbol} must be an @dfn{error symbol}---a symbol
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
833 bearing a property @code{error-conditions} whose value is a list of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
834 condition names. This is how XEmacs Lisp classifies different sorts of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
835 errors.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
836
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
837 The number and significance of the objects in @var{data} depends on
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
838 @var{error-symbol}. For example, with a @code{wrong-type-argument}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
839 error, there are two objects in the list: a predicate that describes the
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
840 type that was expected, and the object that failed to fit that type.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
841 @xref{Error Symbols}, for a description of error symbols.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
842
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
843 Both @var{error-symbol} and @var{data} are available to any error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
844 handlers that handle the error: @code{condition-case} binds a local
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
845 variable to a list of the form @code{(@var{error-symbol} .@:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
846 @var{data})} (@pxref{Handling Errors}). If the error is not handled,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
847 these two values are used in printing the error message.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
848
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
849 The function @code{signal} can return, if the debugger is invoked and
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
850 the user invokes the ``return from signal'' option. If you want the
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
851 error not to be continuable, use @code{signal-error} instead. Note that
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
852 in FSF Emacs @code{signal} never returns.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
853
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
854 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
855 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
856 (signal 'wrong-number-of-arguments '(x y))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
857 @error{} Wrong number of arguments: x, y
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
858 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
859
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
860 @group
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
861 (signal 'no-such-error '("My unknown error condition"))
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
862 @error{} Peculiar error (no-such-error "My unknown error condition")
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
863 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
864 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
865 @end defun
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
866
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
867 @defun signal-error error-symbol data
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
868 This function behaves like @code{signal}, except that the error it
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
869 signals is not continuable.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
870 @end defun
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
871
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
872 @defmac check-argument-type predicate argument
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
873 This macro checks that @var{argument} satisfies @var{predicate}. If
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
874 that is not the case, it signals a continuable
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
875 @code{wrong-type-argument} error until the returned value satisfies
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
876 @var{predicate}, and assigns the returned value to @var{argument}. In
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
877 other words, execution of the program will not continue until
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
878 @var{predicate} is met.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
879
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
880 @var{argument} is not evaluated, and should be a symbol.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
881 @var{predicate} is evaluated, and should name a function.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
882
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
883 As shown in the following example, @code{check-argument-type} is useful
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
884 in low-level code that attempts to ensure the sanity of its data before
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
885 proceeding.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
886
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
887 @example
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
888 @group
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
889 (defun cache-object-internal (object wlist)
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
890 ;; @r{Before doing anything, make sure that @var{wlist} is indeed}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
891 ;; @r{a weak list, which is what we expect.}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
892 (check-argument-type 'weak-list-p wlist)
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
893 @dots{})
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
894 @end group
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
895 @end example
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
896 @end defmac
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
897
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
898 @node Processing of Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
899 @subsubsection How XEmacs Processes Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
900
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
901 When an error is signaled, @code{signal} searches for an active
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
902 @dfn{handler} for the error. A handler is a sequence of Lisp
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
903 expressions designated to be executed if an error happens in part of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
904 Lisp program. If the error has an applicable handler, the handler is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
905 executed, and control resumes following the handler. The handler
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
906 executes in the environment of the @code{condition-case} that
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
907 established it; all functions called within that @code{condition-case}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
908 have already been exited, and the handler cannot return to them.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
909
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
910 If there is no applicable handler for the error, the current command is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
911 terminated and control returns to the editor command loop, because the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
912 command loop has an implicit handler for all kinds of errors. The
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
913 command loop's handler uses the error symbol and associated data to
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
914 print an error message.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
915
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
916 Errors in command loop are processed using the @code{command-error}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
917 function, which takes care of some necessary cleanup, and prints a
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
918 formatted error message to the echo area. The functions that do the
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
919 formatting are explained below.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
920
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
921 @defun display-error error-object stream
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
922 This function displays @var{error-object} on @var{stream}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
923 @var{error-object} is a cons of error type, a symbol, and error
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
924 arguments, a list. If the error type symbol of one of its error
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
925 condition superclasses has an @code{display-error} property, that
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
926 function is invoked for printing the actual error message. Otherwise,
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
927 the error is printed as @samp{Error: arg1, arg2, ...}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
928 @end defun
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
929
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
930 @defun error-message-string error-object
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
931 This function converts @var{error-object} to an error message string,
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
932 and returns it. The message is equivalent to the one that would be
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
933 printed by @code{display-error}, except that it is conveniently returned
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
934 in string form.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
935 @end defun
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
936
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
937 @cindex @code{debug-on-error} use
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
938 An error that has no explicit handler may call the Lisp debugger. The
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
939 debugger is enabled if the variable @code{debug-on-error} (@pxref{Error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
940 Debugging}) is non-@code{nil}. Unlike error handlers, the debugger runs
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
941 in the environment of the error, so that you can examine values of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
942 variables precisely as they were at the time of the error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
943
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
944 @node Handling Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
945 @subsubsection Writing Code to Handle Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
946 @cindex error handler
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
947 @cindex handling errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
948
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
949 The usual effect of signaling an error is to terminate the command
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
950 that is running and return immediately to the XEmacs editor command loop.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
951 You can arrange to trap errors occurring in a part of your program by
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
952 establishing an error handler, with the special form
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
953 @code{condition-case}. A simple example looks like this:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
954
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
955 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
956 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
957 (condition-case nil
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
958 (delete-file filename)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
959 (error nil))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
960 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
961 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
962
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
963 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
964 This deletes the file named @var{filename}, catching any error and
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
965 returning @code{nil} if an error occurs.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
966
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
967 The second argument of @code{condition-case} is called the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
968 @dfn{protected form}. (In the example above, the protected form is a
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
969 call to @code{delete-file}.) The error handlers go into effect when
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
970 this form begins execution and are deactivated when this form returns.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
971 They remain in effect for all the intervening time. In particular, they
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
972 are in effect during the execution of functions called by this form, in
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
973 their subroutines, and so on. This is a good thing, since, strictly
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
974 speaking, errors can be signaled only by Lisp primitives (including
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
975 @code{signal} and @code{error}) called by the protected form, not by the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
976 protected form itself.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
977
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
978 The arguments after the protected form are handlers. Each handler
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
979 lists one or more @dfn{condition names} (which are symbols) to specify
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
980 which errors it will handle. The error symbol specified when an error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
981 is signaled also defines a list of condition names. A handler applies
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
982 to an error if they have any condition names in common. In the example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
983 above, there is one handler, and it specifies one condition name,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
984 @code{error}, which covers all errors.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
985
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
986 The search for an applicable handler checks all the established handlers
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
987 starting with the most recently established one. Thus, if two nested
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
988 @code{condition-case} forms offer to handle the same error, the inner of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
989 the two will actually handle it.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
990
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
991 When an error is handled, control returns to the handler. Before this
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
992 happens, XEmacs unbinds all variable bindings made by binding constructs
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
993 that are being exited and executes the cleanups of all
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
994 @code{unwind-protect} forms that are exited. Once control arrives at
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
995 the handler, the body of the handler is executed.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
996
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
997 After execution of the handler body, execution continues by returning
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
998 from the @code{condition-case} form. Because the protected form is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
999 exited completely before execution of the handler, the handler cannot
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1000 resume execution at the point of the error, nor can it examine variable
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1001 bindings that were made within the protected form. All it can do is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1002 clean up and proceed.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1003
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1004 @code{condition-case} is often used to trap errors that are
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1005 predictable, such as failure to open a file in a call to
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1006 @code{insert-file-contents}. It is also used to trap errors that are
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1007 totally unpredictable, such as when the program evaluates an expression
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1008 read from the user.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1009
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1010 @cindex @code{debug-on-signal} use
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1011 Even when an error is handled, the debugger may still be called if the
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1012 variable @code{debug-on-signal} (@pxref{Error Debugging}) is
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1013 non-@code{nil}. Note that this may yield unpredictable results with
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1014 code that traps expected errors as normal part of its operation. Do not
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1015 set @code{debug-on-signal} unless you know what you are doing.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1016
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1017 Error signaling and handling have some resemblance to @code{throw} and
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1018 @code{catch}, but they are entirely separate facilities. An error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1019 cannot be caught by a @code{catch}, and a @code{throw} cannot be handled
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1020 by an error handler (though using @code{throw} when there is no suitable
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1021 @code{catch} signals an error that can be handled).
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1022
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1023 @defspec condition-case var protected-form handlers@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1024 This special form establishes the error handlers @var{handlers} around
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1025 the execution of @var{protected-form}. If @var{protected-form} executes
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1026 without error, the value it returns becomes the value of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1027 @code{condition-case} form; in this case, the @code{condition-case} has
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1028 no effect. The @code{condition-case} form makes a difference when an
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1029 error occurs during @var{protected-form}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1030
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1031 Each of the @var{handlers} is a list of the form @code{(@var{conditions}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1032 @var{body}@dots{})}. Here @var{conditions} is an error condition name
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1033 to be handled, or a list of condition names; @var{body} is one or more
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1034 Lisp expressions to be executed when this handler handles an error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1035 Here are examples of handlers:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1036
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1037 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1038 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1039 (error nil)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1040
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1041 (arith-error (message "Division by zero"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1042
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1043 ((arith-error file-error)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1044 (message
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1045 "Either division by zero or failure to open a file"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1046 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1047 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1048
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1049 Each error that occurs has an @dfn{error symbol} that describes what
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1050 kind of error it is. The @code{error-conditions} property of this
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1051 symbol is a list of condition names (@pxref{Error Symbols}). Emacs
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1052 searches all the active @code{condition-case} forms for a handler that
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1053 specifies one or more of these condition names; the innermost matching
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1054 @code{condition-case} handles the error. Within this
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1055 @code{condition-case}, the first applicable handler handles the error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1056
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1057 After executing the body of the handler, the @code{condition-case}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1058 returns normally, using the value of the last form in the handler body
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1059 as the overall value.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1060
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1061 The argument @var{var} is a variable. @code{condition-case} does not
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1062 bind this variable when executing the @var{protected-form}, only when it
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1063 handles an error. At that time, it binds @var{var} locally to a list of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1064 the form @code{(@var{error-symbol} . @var{data})}, giving the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1065 particulars of the error. The handler can refer to this list to decide
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1066 what to do. For example, if the error is for failure opening a file,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1067 the file name is the second element of @var{data}---the third element of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1068 @var{var}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1069
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1070 If @var{var} is @code{nil}, that means no variable is bound. Then the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1071 error symbol and associated data are not available to the handler.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1072 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1073
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1074 @cindex @code{arith-error} example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1075 Here is an example of using @code{condition-case} to handle the error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1076 that results from dividing by zero. The handler prints out a warning
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1077 message and returns a very large number.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1078
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1079 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1080 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1081 (defun safe-divide (dividend divisor)
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
1082 (condition-case err
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1083 ;; @r{Protected form.}
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
1084 (/ dividend divisor)
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1085 ;; @r{The handler.}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1086 (arith-error ; @r{Condition.}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1087 (princ (format "Arithmetic error: %s" err))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1088 1000000)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1089 @result{} safe-divide
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1090 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1091
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1092 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1093 (safe-divide 5 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1094 @print{} Arithmetic error: (arith-error)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1095 @result{} 1000000
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1096 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1097 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1098
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1099 @noindent
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1100 The handler specifies condition name @code{arith-error} so that it will
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1101 handle only division-by-zero errors. Other kinds of errors will not be
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1102 handled, at least not by this @code{condition-case}. Thus,
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1103
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1104 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1105 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1106 (safe-divide nil 3)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1107 @error{} Wrong type argument: integer-or-marker-p, nil
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1108 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1109 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1110
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1111 Here is a @code{condition-case} that catches all kinds of errors,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1112 including those signaled with @code{error}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1113
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1114 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1115 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1116 (setq baz 34)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1117 @result{} 34
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1118 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1119
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1120 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1121 (condition-case err
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1122 (if (eq baz 35)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1123 t
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1124 ;; @r{This is a call to the function @code{error}.}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1125 (error "Rats! The variable %s was %s, not 35" 'baz baz))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1126 ;; @r{This is the handler; it is not a form.}
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
1127 (error (princ (format "The error was: %s" err))
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1128 2))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1129 @print{} The error was: (error "Rats! The variable baz was 34, not 35")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1130 @result{} 2
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1131 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1132 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1133
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1134 @node Error Symbols
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1135 @subsubsection Error Symbols and Condition Names
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1136 @cindex error symbol
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1137 @cindex error name
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1138 @cindex condition name
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1139 @cindex user-defined error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1140 @kindex error-conditions
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1141
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1142 When you signal an error, you specify an @dfn{error symbol} to specify
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1143 the kind of error you have in mind. Each error has one and only one
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1144 error symbol to categorize it. This is the finest classification of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1145 errors defined by the XEmacs Lisp language.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1146
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1147 These narrow classifications are grouped into a hierarchy of wider
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1148 classes called @dfn{error conditions}, identified by @dfn{condition
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1149 names}. The narrowest such classes belong to the error symbols
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1150 themselves: each error symbol is also a condition name. There are also
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1151 condition names for more extensive classes, up to the condition name
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1152 @code{error} which takes in all kinds of errors. Thus, each error has
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1153 one or more condition names: @code{error}, the error symbol if that
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1154 is distinct from @code{error}, and perhaps some intermediate
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1155 classifications.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1156
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1157 In other words, each error condition @dfn{inherits} from another error
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1158 condition, with @code{error} sitting at the top of the inheritance
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1159 hierarchy.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1160
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1161 @defun define-error error-symbol error-message &optional inherits-from
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1162 This function defines a new error, denoted by @var{error-symbol}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1163 @var{error-message} is an informative message explaining the error, and
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1164 will be printed out when an unhandled error occurs. @var{error-symbol}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1165 is a sub-error of @var{inherits-from} (which defaults to @code{error}).
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1166
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1167 @code{define-error} internally works by putting on @var{error-symbol}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1168 an @code{error-message} property whose value is @var{error-message}, and
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1169 an @code{error-conditions} property that is a list of @var{error-symbol}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1170 followed by each of its super-errors, up to and including @code{error}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1171 You will sometimes see code that sets this up directly rather than
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1172 calling @code{define-error}, but you should @emph{not} do this yourself,
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1173 unless you wish to maintain compatibility with FSF Emacs, which does not
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1174 provide @code{define-error}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1175 @end defun
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1176
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1177 Here is how we define a new error symbol, @code{new-error}, that
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1178 belongs to a range of errors called @code{my-own-errors}:
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1179
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1180 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1181 @group
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1182 (define-error 'my-own-errors "A whole range of errors" 'error)
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1183 (define-error 'new-error "A new error" 'my-own-errors)
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1184 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1185 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1186
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1187 @noindent
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1188 @code{new-error} has three condition names: @code{new-error}, the
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1189 narrowest classification; @code{my-own-errors}, which we imagine is a
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1190 wider classification; and @code{error}, which is the widest of all.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1191
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1192 Note that it is not legal to try to define an error unless its
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1193 super-error is also defined. For instance, attempting to define
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1194 @code{new-error} before @code{my-own-errors} are defined will signal an
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1195 error.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1196
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1197 The error string should start with a capital letter but it should
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1198 not end with a period. This is for consistency with the rest of Emacs.
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1199
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1200 Naturally, XEmacs will never signal @code{new-error} on its own; only
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1201 an explicit call to @code{signal} (@pxref{Signaling Errors}) in your
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1202 code can do this:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1203
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1204 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1205 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1206 (signal 'new-error '(x y))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1207 @error{} A new error: x, y
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1208 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1209 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1210
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1211 This error can be handled through any of the three condition names.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1212 This example handles @code{new-error} and any other errors in the class
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1213 @code{my-own-errors}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1214
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1215 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1216 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1217 (condition-case foo
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1218 (bar nil t)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1219 (my-own-errors nil))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1220 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1221 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1222
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1223 The significant way that errors are classified is by their condition
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1224 names---the names used to match errors with handlers. An error symbol
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1225 serves only as a convenient way to specify the intended error message
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1226 and list of condition names. It would be cumbersome to give
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1227 @code{signal} a list of condition names rather than one error symbol.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1228
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1229 By contrast, using only error symbols without condition names would
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1230 seriously decrease the power of @code{condition-case}. Condition names
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1231 make it possible to categorize errors at various levels of generality
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1232 when you write an error handler. Using error symbols alone would
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1233 eliminate all but the narrowest level of classification.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1234
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
1235
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1236
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1237 @xref{Standard Errors}, for a list of all the standard error symbols
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1238 and their conditions.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1239
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1240 @node Cleanups
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1241 @subsection Cleaning Up from Nonlocal Exits
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1242
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1243 The @code{unwind-protect} construct is essential whenever you
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1244 temporarily put a data structure in an inconsistent state; it permits
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1245 you to ensure the data are consistent in the event of an error or throw.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1246
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1247 @defspec unwind-protect body cleanup-forms@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1248 @cindex cleanup forms
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1249 @cindex protected forms
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1250 @cindex error cleanup
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1251 @cindex unwinding
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1252 @code{unwind-protect} executes the @var{body} with a guarantee that the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1253 @var{cleanup-forms} will be evaluated if control leaves @var{body}, no
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1254 matter how that happens. The @var{body} may complete normally, or
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1255 execute a @code{throw} out of the @code{unwind-protect}, or cause an
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1256 error; in all cases, the @var{cleanup-forms} will be evaluated.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1257
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1258 If the @var{body} forms finish normally, @code{unwind-protect} returns
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1259 the value of the last @var{body} form, after it evaluates the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1260 @var{cleanup-forms}. If the @var{body} forms do not finish,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1261 @code{unwind-protect} does not return any value in the normal sense.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1262
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1263 Only the @var{body} is actually protected by the @code{unwind-protect}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1264 If any of the @var{cleanup-forms} themselves exits nonlocally (e.g., via
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1265 a @code{throw} or an error), @code{unwind-protect} is @emph{not}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1266 guaranteed to evaluate the rest of them. If the failure of one of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1267 @var{cleanup-forms} has the potential to cause trouble, then protect it
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1268 with another @code{unwind-protect} around that form.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1269
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1270 The number of currently active @code{unwind-protect} forms counts,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1271 together with the number of local variable bindings, against the limit
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1272 @code{max-specpdl-size} (@pxref{Local Variables}).
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1273 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1274
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1275 For example, here we make an invisible buffer for temporary use, and
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1276 make sure to kill it before finishing:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1277
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1278 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1279 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1280 (save-excursion
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1281 (let ((buffer (get-buffer-create " *temp*")))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1282 (set-buffer buffer)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1283 (unwind-protect
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1284 @var{body}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1285 (kill-buffer buffer))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1286 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1287 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1288
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1289 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1290 You might think that we could just as well write @code{(kill-buffer
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1291 (current-buffer))} and dispense with the variable @code{buffer}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1292 However, the way shown above is safer, if @var{body} happens to get an
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1293 error after switching to a different buffer! (Alternatively, you could
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1294 write another @code{save-excursion} around the body, to ensure that the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1295 temporary buffer becomes current in time to kill it.)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1296
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1297 @findex ftp-login
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1298 Here is an actual example taken from the file @file{ftp.el}. It
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1299 creates a process (@pxref{Processes}) to try to establish a connection
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1300 to a remote machine. As the function @code{ftp-login} is highly
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1301 susceptible to numerous problems that the writer of the function cannot
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1302 anticipate, it is protected with a form that guarantees deletion of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1303 process in the event of failure. Otherwise, XEmacs might fill up with
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1304 useless subprocesses.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1305
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1306 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1307 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1308 (let ((win nil))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1309 (unwind-protect
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1310 (progn
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1311 (setq process (ftp-setup-buffer host file))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1312 (if (setq win (ftp-login process host user password))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1313 (message "Logged in")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1314 (error "Ftp login failed")))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1315 (or win (and process (delete-process process)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1316 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1317 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1318
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1319 This example actually has a small bug: if the user types @kbd{C-g} to
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1320 quit, and the quit happens immediately after the function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1321 @code{ftp-setup-buffer} returns but before the variable @code{process} is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1322 set, the process will not be killed. There is no easy way to fix this bug,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1323 but at least it is very unlikely.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1324
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1325 Here is another example which uses @code{unwind-protect} to make sure
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1326 to kill a temporary buffer. In this example, the value returned by
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1327 @code{unwind-protect} is used.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1328
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1329 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1330 (defun shell-command-string (cmd)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1331 "Return the output of the shell command CMD, as a string."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1332 (save-excursion
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1333 (set-buffer (generate-new-buffer " OS*cmd"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1334 (shell-command cmd t)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1335 (unwind-protect
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1336 (buffer-string)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1337 (kill-buffer (current-buffer)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1338 @end smallexample