annotate man/lispref/control.texi @ 5353:38e24b8be4ea

Improve the lexical scoping in #'block, #'return-from. lisp/ChangeLog addition: 2011-02-07 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el: * bytecomp.el (byte-compile-initial-macro-environment): Shadow `block', `return-from' here, we implement them differently when byte-compiling. * bytecomp.el (byte-compile-active-blocks): New. * bytecomp.el (byte-compile-block-1): New. * bytecomp.el (byte-compile-return-from-1): New. * bytecomp.el (return-from-1): New. * bytecomp.el (block-1): New. These are two aliases that exist to have their own associated byte-compile functions, which functions implement `block' and `return-from'. * cl-extra.el (cl-macroexpand-all): Fix a bug here when macros in the environment have been compiled. * cl-macs.el (block): * cl-macs.el (return): * cl-macs.el (return-from): Be more careful about lexical scope in these macros. * cl.el: * cl.el ('cl-block-wrapper): Removed. * cl.el ('cl-block-throw): Removed. These aren't needed in code generated by this XEmacs. They shouldn't be needed in code generated by XEmacs 21.4, but if it turns out the packages do need them, we can put them back. 2011-01-30 Mike Sperber <mike@xemacs.org> * font-lock.el (font-lock-fontify-pending-extents): Don't fail if `font-lock-mode' is unset, which can happen in the middle of `revert-buffer'. 2011-01-23 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (delete): * cl-macs.el (delq): * cl-macs.el (remove): * cl-macs.el (remq): Don't use the compiler macro if these functions were given the wrong number of arguments, as happens in lisp-tests.el. * cl-seq.el (remove, remq): Removed. I added these to subr.el, and forgot to remove them from here. 2011-01-22 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el (byte-compile-setq, byte-compile-set): Remove kludge allowing keywords' values to be set, all the code that does that is gone. * cl-compat.el (elt-satisfies-test-p): * faces.el (set-face-parent): * faces.el (face-doc-string): * gtk-font-menu.el: * gtk-font-menu.el (gtk-reset-device-font-menus): * msw-font-menu.el: * msw-font-menu.el (mswindows-reset-device-font-menus): * package-get.el (package-get-installedp): * select.el (select-convert-from-image-data): * sound.el: * sound.el (load-sound-file): * x-font-menu.el (x-reset-device-font-menus-core): Don't quote keywords, they're self-quoting, and the win from backward-compatibility is sufficiently small now that the style problem overrides it. 2011-01-22 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (block, return-from): Require that NAME be a symbol in these macros, as always documented in the #'block docstring and as required by Common Lisp. * descr-text.el (unidata-initialize-unihan-database): Correct the use of non-symbols in #'block and #'return-from in this function. 2011-01-15 Aidan Kehoe <kehoea@parhasard.net> * cl-extra.el (concatenate): Accept more complicated TYPEs in this function, handing the sequences over to #'coerce if we don't understand them here. * cl-macs.el (inline): Don't proclaim #'concatenate as inline, its compiler macro is more useful than doing that. 2011-01-11 Aidan Kehoe <kehoea@parhasard.net> * subr.el (delete, delq, remove, remq): Move #'remove, #'remq here, they don't belong in cl-seq.el; move #'delete, #'delq here from fns.c, implement them in terms of #'delete*, allowing support for sequences generally. * update-elc.el (do-autoload-commands): Use #'delete*, not #'delq here, now the latter's no longer dumped. * cl-macs.el (delete, delq): Add compiler macros transforming #'delete and #'delq to #'delete* calls. 2011-01-10 Aidan Kehoe <kehoea@parhasard.net> * dialog.el (make-dialog-box): Correct a misplaced parenthesis here, thank you Mats Lidell in 87zkr9gqrh.fsf@mail.contactor.se ! 2011-01-02 Aidan Kehoe <kehoea@parhasard.net> * dialog.el (make-dialog-box): * list-mode.el (display-completion-list): These functions used to use cl-parsing-keywords; change them to use defun* instead, fixing the build. (Not sure what led to me not including this change in d1b17a33450b!) 2011-01-02 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (define-star-compiler-macros): Make sure the form has ITEM and LIST specified before attempting to change to calls with explicit tests; necessary for some tests in lisp-tests.el to compile correctly. (stable-union, stable-intersection): Add compiler macros for these functions, in the same way we do for most of the other functions in cl-seq.el. 2011-01-01 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (dolist, dotimes, do-symbols, macrolet) (symbol-macrolet): Define these macros with defmacro* instead of parsing the argument list by hand, for the sake of style and readability; use backquote where appropriate, instead of calling #'list and and friends, for the same reason. 2010-12-30 Aidan Kehoe <kehoea@parhasard.net> * x-misc.el (device-x-display): Provide this function, documented in the Lispref for years, but not existing previously. Thank you Julian Bradfield, thank you Jeff Mincy. 2010-12-30 Aidan Kehoe <kehoea@parhasard.net> * cl-seq.el: Move the heavy lifting from this file to C. Dump the cl-parsing-keywords macro, but don't use defun* for the functions we define that do take keywords, dynamic scope lossage makes that not practical. * subr.el (sort, fillarray): Move these aliases here. (map-plist): #'nsublis is now built-in, but at this point #'eql isn't necessarily available as a test; use #'eq. * obsolete.el (cl-delete-duplicates): Make this available for old compiler macros and old code. (memql): Document that this is equivalent to #'member*, and worse. * cl.el (adjoin, subst): Removed. These are in C. 2010-12-30 Aidan Kehoe <kehoea@parhasard.net> * simple.el (assoc-ignore-case): Remove a duplicate definition of this function (it's already in subr.el). * iso8859-1.el (char-width): On non-Mule, make this function equivalent to that produced by (constantly 1), but preserve its docstring. * subr.el (subst-char-in-string): Define this in terms of #'substitute, #'nsubstitute. (string-width): Define this using #'reduce and #'char-width. (char-width): Give this a simpler definition, it makes far more sense to check for mule at load time and redefine, as we do in iso8859-1.el. (store-substring): Implement this in terms of #'replace, now #'replace is cheap. 2010-12-30 Aidan Kehoe <kehoea@parhasard.net> * update-elc.el (lisp-files-needed-for-byte-compilation) (lisp-files-needing-early-byte-compilation): cl-macs belongs in the former, not the latter, it is as fundamental as bytecomp.el. 2010-12-30 Aidan Kehoe <kehoea@parhasard.net> * cl.el: Provde the Common Lisp program-error, type-error as error symbols. This doesn't nearly go far enough for anyone using the Common Lisp errors. 2010-12-29 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (delete-duplicates): If the form has an incorrect number of arguments, don't attempt a compiler macroexpansion. 2010-12-29 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (cl-safe-expr-p): Forms that start with the symbol lambda are also safe. 2010-12-29 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (= < > <= >=): For these functions' compiler macros, the optimisation is safe even if the first and the last arguments have side effects, since they're only used the once. 2010-12-29 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (inline-side-effect-free-compiler-macros): Unroll a loop here at macro-expansion time, so these compiler macros are compiled. Use #'eql instead of #'eq in a couple of places for better style. 2010-12-29 Aidan Kehoe <kehoea@parhasard.net> * cl-extra.el (notany, notevery): Avoid some dynamic scope stupidity with local variable names in these functions, when they weren't prefixed with cl-; go into some more detail in the doc strings. 2010-12-29 Aidan Kehoe <kehoea@parhasard.net> * byte-optimize.el (side-effect-free-fns): #'remove, #'remq are free of side-effects. (side-effect-and-error-free-fns): Drop dot, dot-marker from the list. 2010-11-17 Aidan Kehoe <kehoea@parhasard.net> * cl-extra.el (coerce): In the argument list, name the first argument OBJECT, not X; the former name was always used in the doc string and is clearer. Handle vector type specifications which include the length of the target sequence, error if there's a mismatch. * cl-macs.el (cl-make-type-test): Handle type specifications starting with the symbol 'eql. 2010-11-14 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (eql): Don't remove the byte-compile property of this symbol. That was necessary to override a bug in bytecomp.el where #'eql was confused with #'eq, which bug we no longer have. If neither expression is constant, don't attempt to handle the expression in this compiler macro, leave it to byte-compile-eql, which produces better code anyway. * bytecomp.el (eq): #'eql is not the function associated with the byte-eq byte code. (byte-compile-eql): Add an explicit compile method for this function, for cases where the cl-macs compiler macro hasn't reduced it to #'eq or #'equal. 2010-10-25 Aidan Kehoe <kehoea@parhasard.net> Add compiler macros and compilation sanity-checking for various functions that take keywords. * byte-optimize.el (side-effect-free-fns): #'symbol-value is side-effect free and not error free. * bytecomp.el (byte-compile-normal-call): Check keyword argument lists for sanity; store information about the positions where keyword arguments start using the new byte-compile-keyword-start property. * cl-macs.el (cl-const-expr-val): Take a new optional argument, cl-not-constant, defaulting to nil, in this function; return it if the expression is not constant. (cl-non-fixnum-number-p): Make this into a separate function, we want to pass it to #'every. (eql): Use it. (define-star-compiler-macros): Use the same code to generate the member*, assoc* and rassoc* compiler macros; special-case some code in #'add-to-list in subr.el. (remove, remq): Add compiler macros for these two functions, in preparation for #'remove being in C. (define-foo-if-compiler-macros): Transform (remove-if-not ...) calls to (remove ... :if-not) at compile time, which will be a real win once the latter is in C. (define-substitute-if-compiler-macros) (define-subst-if-compiler-macros): Similarly for these functions. (delete-duplicates): Change this compiler macro to use #'plists-equal; if we don't have information about the type of SEQUENCE at compile time, don't bother attempting to inline the call, the function will be in C soon enough. (equalp): Remove an old commented-out compiler macro for this, if we want to see it it's in version control. (subst-char-in-string): Transform this to a call to nsubstitute or nsubstitute, if that is appropriate. * cl.el (ldiff): Don't call setf here, this makes for a load-time dependency problem in cl-macs.el 2010-06-14 Stephen J. Turnbull <stephen@xemacs.org> * term/vt100.el: Refer to XEmacs, not GNU Emacs, in permissions. * term/bg-mouse.el: * term/sup-mouse.el: Put copyright notice in canonical "Copyright DATE AUTHOR" form. Refer to XEmacs, not GNU Emacs, in permissions. * site-load.el: Add permission boilerplate. * mule/canna-leim.el: * alist.el: Refer to XEmacs, not APEL/this program, in permissions. * mule/canna-leim.el: Remove my copyright, I've assigned it to the FSF. 2010-06-14 Stephen J. Turnbull <stephen@xemacs.org> * gtk.el: * gtk-widget-accessors.el: * gtk-package.el: * gtk-marshal.el: * gtk-compose.el: * gnome.el: Add copyright notice based on internal evidence. 2010-06-14 Stephen J. Turnbull <stephen@xemacs.org> * easymenu.el: Add reference to COPYING to permission notice. * gutter.el: * gutter-items.el: * menubar-items.el: Fix typo "Xmacs" in permissions notice. 2010-06-14 Stephen J. Turnbull <stephen@xemacs.org> * auto-save.el: * font.el: * fontconfig.el: * mule/kinsoku.el: Add "part of XEmacs" text to permission notice. 2010-10-14 Aidan Kehoe <kehoea@parhasard.net> * byte-optimize.el (side-effect-free-fns): * cl-macs.el (remf, getf): * cl-extra.el (tailp, cl-set-getf, cl-do-remf): * cl.el (ldiff, endp): Tighten up Common Lisp compatibility for #'ldiff, #'endp, #'tailp; add circularity checking for the first two. #'cl-set-getf and #'cl-do-remf were Lisp implementations of #'plist-put and #'plist-remprop; change the names to aliases, changes the macros that use them to using #'plist-put and #'plist-remprop directly. 2010-10-12 Aidan Kehoe <kehoea@parhasard.net> * abbrev.el (fundamental-mode-abbrev-table, global-abbrev-table): Create both these abbrev tables using the usual #'define-abbrev-table calls, rather than attempting to special-case them. * cl-extra.el: Force cl-macs to be loaded here, if cl-extra.el is being loaded interpreted. Previously other, later files would redundantly call (load "cl-macs") when interpreted, it's more reasonable to do it here, once. * cmdloop.el (read-quoted-char-radix): Use defcustom here, we don't have any dump-order dependencies that would prevent that. * custom.el (eval-when-compile): Don't load cl-macs when interpreted or when byte-compiling, rely on cl-extra.el in the former case and the appropriate entry in bytecomp-load-hook in the latter. Get rid of custom-declare-variable-list, we have no dump-time dependencies that would require it. * faces.el (eval-when-compile): Don't load cl-macs when interpreted or when byte-compiling. * packages.el: Remove some inaccurate comments. * post-gc.el (cleanup-simple-finalizers): Use #'delete-if-not here, now the order of preloaded-file-list has been changed to make it available. * subr.el (custom-declare-variable-list): Remove. No need for it. Also remove a stub define-abbrev-table from this file, given the current order of preloaded-file-list there's no need for it. 2010-10-10 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el (byte-compile-constp) Forms quoted with FUNCTION are also constant. (byte-compile-initial-macro-environment): In #'the, if FORM is constant and does not match TYPE, warn at byte-compile time. 2010-10-10 Aidan Kehoe <kehoea@parhasard.net> * backquote.el (bq-vector-contents, bq-list*): Remove; the former is equivalent to (append VECTOR nil), the latter to (list* ...). (bq-process-2): Use (append VECTOR nil) instead of using #'bq-vector-contents to convert to a list. (bq-process-1): Now we use list* instead of bq-list * subr.el (list*): Moved from cl.el, since it is now required to be available the first time a backquoted form is encountered. * cl.el (list*): Move to subr.el. 2010-09-16 Aidan Kehoe <kehoea@parhasard.net> * test-harness.el (Check-Message): Add an omitted comma here, thank you the buildbot. 2010-09-16 Aidan Kehoe <kehoea@parhasard.net> * hash-table.el (hash-table-key-list, hash-table-value-list) (hash-table-key-value-alist, hash-table-key-value-plist): Remove some useless #'nreverse calls in these files; our hash tables have no order, it's not helpful to pretend they do. * behavior.el (read-behavior): Do the same in this file, in some code evidently copied from hash-table.el. 2010-09-16 Aidan Kehoe <kehoea@parhasard.net> * info.el (Info-insert-dir): * format.el (format-deannotate-region): * files.el (cd, save-buffers-kill-emacs): Use #'some, #'every and related functions for applying boolean operations to lists, instead of rolling our own ones that cons and don't short-circuit. 2010-09-16 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el (byte-compile-initial-macro-environment): * cl-macs.el (the): Rephrase the docstring, make its implementation when compiling files a little nicer. 2010-09-16 Aidan Kehoe <kehoea@parhasard.net> * descr-text.el (unidata-initialize-unicodedata-database) (unidata-initialize-unihan-database, describe-char-unicode-data) (describe-char-unicode-data): Wrap calls to the database functions with (with-fboundp ...), avoiding byte compile warnings on builds without support for the database functions. (describe-char): (reduce #'max ...), not (apply #'max ...), no need to cons needlessly. (describe-char): Remove a redundant lambda wrapping #'extent-properties. (describe-char-unicode-data): Call #'nsubst when replacing "" with nil in the result of #'split-string, instead of consing inside mapcar. 2010-09-16 Aidan Kehoe <kehoea@parhasard.net> * x-faces.el (x-available-font-sizes): * specifier.el (let-specifier): * package-ui.el (pui-add-required-packages): * msw-faces.el (mswindows-available-font-sizes): * modeline.el (modeline-minor-mode-menu): * minibuf.el (minibuf-directory-files): Replace the O2N (delq nil (mapcar (lambda (W) (and X Y)) Z)) with the ON (mapcan (lambda (W) (and X (list Y))) Z) in these files. 2010-09-16 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (= < > <= >=): When these functions are handed more than two arguments, and those arguments have no side effects, transform to a series of two argument calls, avoiding funcall in the byte-compiled code. * mule/mule-cmds.el (finish-set-language-environment): Take advantage of this change in a function called 256 times at startup. 2010-09-16 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el (byte-compile-function-form, byte-compile-quote) (byte-compile-quote-form): Warn at compile time, and error at runtime, if a (quote ...) or a (function ...) form attempts to quote more than one object. 2010-09-16 Aidan Kehoe <kehoea@parhasard.net> * byte-optimize.el (byte-optimize-apply): Transform (apply 'nconc (mapcar ...)) to (mapcan ...); warn about use of the first idiom. * update-elc.el (do-autoload-commands): * packages.el (packages-find-package-library-path): * frame.el (frame-list): * extents.el (extent-descendants): * etags.el (buffer-tag-table-files): * dumped-lisp.el (preloaded-file-list): * device.el (device-list): * bytecomp-runtime.el (proclaim-inline, proclaim-notinline) Use #'mapcan, not (apply #'nconc (mapcar ...) in all these files. * bytecomp-runtime.el (eval-when-compile, eval-and-compile): In passing, mention that these macros also evaluate the body when interpreted. tests/ChangeLog addition: 2011-02-07 Aidan Kehoe <kehoea@parhasard.net> * automated/lisp-tests.el: Test lexical scope for `block', `return-from'; add a Known-Bug-Expect-Failure for a contorted example that fails when byte-compiled.
author Aidan Kehoe <kehoea@parhasard.net>
date Mon, 07 Feb 2011 12:01:24 +0000
parents 755ae5b97edb
children 62b9ef1ed4ac
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
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
8 @cindex special operators for control structures
0
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
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
13 @dfn{control structures}. Control structures are special operators which
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
14 control when, whether, or how many times to execute the subforms of
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
15 their containing forms.
0
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
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
32 special operators since their enclosing forms' subforms are not
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
33 necessarily evaluated or not evaluated sequentially. You can use macros
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
34 to define your own control structure constructs (@pxref{Macros}).
0
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{}
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
80 This special operator evaluates all of the @var{forms}, in textual
0
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{}
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
100 This special operator evaluates @var{form1} and all of the @var{forms}, in
0
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{}
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
124 This special operator evaluates @var{form1}, @var{form2}, and all of the
0
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
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
160 @code{if} is a special operator because the branch that is not selected is
0
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{}
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
272 The @code{and} special operator tests whether all the @var{conditions} are
0
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{}
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
326 The @code{or} special operator tests whether at least one of the
0
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
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
382 in XEmacs Lisp with the special operator @code{while}:
0
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
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
491 @code{unwind-protect} special operator when it exits that form
0
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
2297
13a418960a88 [xemacs-hg @ 2004-09-22 02:05:42 by stephent]
stephent
parents: 901
diff changeset
624 In most cases the formal tag for a catch is a quoted symbol or a
13a418960a88 [xemacs-hg @ 2004-09-22 02:05:42 by stephent]
stephent
parents: 901
diff changeset
625 variable whose value is a symbol. Both styles are demonstrated above.
13a418960a88 [xemacs-hg @ 2004-09-22 02:05:42 by stephent]
stephent
parents: 901
diff changeset
626 In definitions of derived control structures, an anonymous tag may be
13a418960a88 [xemacs-hg @ 2004-09-22 02:05:42 by stephent]
stephent
parents: 901
diff changeset
627 desired. A gensym could be used, but since catch tags are compared
13a418960a88 [xemacs-hg @ 2004-09-22 02:05:42 by stephent]
stephent
parents: 901
diff changeset
628 using @code{eq}, any Lisp object can be used. An occasionally
13a418960a88 [xemacs-hg @ 2004-09-22 02:05:42 by stephent]
stephent
parents: 901
diff changeset
629 encountered idiom is to bind a local variable to @code{(cons nil nil)},
13a418960a88 [xemacs-hg @ 2004-09-22 02:05:42 by stephent]
stephent
parents: 901
diff changeset
630 and use the variable as the formal tag.
13a418960a88 [xemacs-hg @ 2004-09-22 02:05:42 by stephent]
stephent
parents: 901
diff changeset
631
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
632 @node Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
633 @subsection Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
634 @cindex errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
635
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
636 When XEmacs Lisp attempts to evaluate a form that, for some reason,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
637 cannot be evaluated, it @dfn{signals} an @dfn{error}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
638
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
639 When an error is signaled, XEmacs's default reaction is to print an
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
640 error message and terminate execution of the current command. This is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
641 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
642 the end of the buffer.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
643
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
644 In complicated programs, simple termination may not be what you want.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
645 For example, the program may have made temporary changes in data
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
646 structures, or created temporary buffers that should be deleted before
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
647 the program is finished. In such cases, you would use
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
648 @code{unwind-protect} to establish @dfn{cleanup expressions} to be
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
649 evaluated in case of error. (@xref{Cleanups}.) Occasionally, you may
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
650 wish the program to continue execution despite an error in a subroutine.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
651 In these cases, you would use @code{condition-case} to establish
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
652 @dfn{error handlers} to recover control in case of error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
653
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
654 Resist the temptation to use error handling to transfer control from
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
655 one part of the program to another; use @code{catch} and @code{throw}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
656 instead. @xref{Catch and Throw}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
657
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
658 @menu
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
659 * Signaling Errors:: How to report an error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
660 * Processing of Errors:: What XEmacs does when you report an error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
661 * Handling Errors:: How you can trap errors and continue execution.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
662 * Error Symbols:: How errors are classified for trapping them.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
663 @end menu
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
664
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
665 @node Signaling Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
666 @subsubsection How to Signal an Error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
667 @cindex signaling errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
668
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
669 Most errors are signaled ``automatically'' within Lisp primitives
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
670 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
671 @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
672 buffer; you can also signal errors explicitly with the functions
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
673 @code{error}, @code{signal}, and others.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
674
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
675 Quitting, which happens when the user types @kbd{C-g}, is not
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
676 considered an error, but it is handled almost like an error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
677 @xref{Quitting}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
678
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
679 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
680
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
681 @example
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
682 error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
683 syntax-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
684 invalid-read-syntax
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
685 list-formation-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
686 malformed-list
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
687 malformed-property-list
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
688 circular-list
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
689 circular-property-list
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
690
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
691 invalid-argument
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
692 wrong-type-argument
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
693 args-out-of-range
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
694 wrong-number-of-arguments
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
695 invalid-function
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
696 no-catch
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
697
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
698 invalid-state
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
699 void-function
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
700 cyclic-function-indirection
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
701 void-variable
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
702 cyclic-variable-indirection
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
703
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
704 invalid-operation
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
705 invalid-change
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
706 setting-constant
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
707 editing-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
708 beginning-of-buffer
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
709 end-of-buffer
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
710 buffer-read-only
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
711 io-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
712 end-of-file
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
713 arith-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
714 range-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
715 domain-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
716 singularity-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
717 overflow-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
718 underflow-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
719 @end example
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
720
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
721 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
722 errors off of are @code{syntax-error}, @code{invalid-argument},
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
723 @code{invalid-state}, @code{invalid-operation}, and
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
724 @code{invalid-change}. Note the semantic differences:
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
725
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
726 @itemize @bullet
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{syntax-error} is for errors in complex structures: parsed strings,
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
729 lists, and the like.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
730
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
731 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
732 @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
733 entire value, not just one part of it, is wrong.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
734
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
735 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
736 @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
737 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
738 being written more carefully, and catches the error when the settings
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
739 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
740 error:
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
741
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
742 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
743 @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
744 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
745 @code{invalid-operation}.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
746
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
747 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
748 @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
749 something that's disallowed. This includes file errors, buffer errors
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
750 (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
751 mentioned, and arithmetic errors.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
752 @end itemize
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
753
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
754 @defun error datum &rest args
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
755 This function signals a non-continuable error.
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 @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
758 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
759 @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
760 the most basic error handling function.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
761
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
762 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
763 error using the debugger @kbd{r} command. See also @code{cerror}.
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 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
766 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
767 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
768 operation being performed and what went wrong), and the remaining
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
769 arguments or \"frobs\" (most often, there is one) specify the offending
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
770 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
771 a file error occurred, e.g.:
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
772
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
773 @itemize @bullet
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
774 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
775 the buffer in which an editing error occurred.
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 an invalid value that was encountered. (In such cases, the string
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
778 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
779 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
780 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
781 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
782 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
783 that's not self-evident.)
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
784 @item
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
785 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
786 second frob, probably a string, specifying the exact error that occurred.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
787 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
788 that frob describes the exact operation that was happening.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
789 @end itemize
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 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
792 @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
793 @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
794 @code{error} and formatted string. Although this usage of @code{error}
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
795 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
796 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
797 to use.
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
798
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
799 See also @code{cerror}, @code{signal}, and @code{signal-error}."
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
800
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
801 These examples show typical uses of @code{error}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
802
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
803 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
804 @group
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
805 (error 'syntax-error
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
806 "Dialog descriptor must supply at least one button"
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
807 descriptor)
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
808 @end group
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
809
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
810 @group
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
811 (error "You have committed an error.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
812 Try something else.")
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
813 @error{} You have committed an error.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
814 Try something else.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
815 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
816
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
817 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
818 (error "You have committed %d errors." 10)
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
819 @error{} You have committed 10 errors.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
820 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
821 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
822
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
823 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
824 just write @code{(error @var{string})}. If @var{string} contains
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
825 @samp{%}, it will be interpreted as a format specifier, with undesirable
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
826 results. Instead, use @code{(error "%s" @var{string})}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
827 @end defun
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
828
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
829 @defun cerror datum &rest args
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
830 This function behaves like @code{error}, except that the error it
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
831 signals is continuable. That means that debugger commands @kbd{c} and
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
832 @kbd{r} can resume execution.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
833 @end defun
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
834
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
835 @defun signal error-symbol data
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
836 This function signals a continuable error named by @var{error-symbol}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
837 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
838 the circumstances of the error.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
839
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
840 The argument @var{error-symbol} must be an @dfn{error symbol}---a symbol
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
841 bearing a property @code{error-conditions} whose value is a list of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
842 condition names. This is how XEmacs Lisp classifies different sorts of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
843 errors.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
844
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
845 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
846 @var{error-symbol}. For example, with a @code{wrong-type-argument}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
847 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
848 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
849 @xref{Error Symbols}, for a description of error symbols.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
850
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
851 Both @var{error-symbol} and @var{data} are available to any error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
852 handlers that handle the error: @code{condition-case} binds a local
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
853 variable to a list of the form @code{(@var{error-symbol} .@:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
854 @var{data})} (@pxref{Handling Errors}). If the error is not handled,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
855 these two values are used in printing the error message.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
856
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
857 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
858 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
859 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
860 in FSF Emacs @code{signal} never returns.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
861
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
862 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
863 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
864 (signal 'wrong-number-of-arguments '(x y))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
865 @error{} Wrong number of arguments: x, y
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
866 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
867
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
868 @group
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
869 (signal 'no-such-error '("My unknown error condition"))
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
870 @error{} Peculiar error (no-such-error "My unknown error condition")
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
871 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
872 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
873 @end defun
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
874
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
875 @defun signal-error error-symbol data
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
876 This function behaves like @code{signal}, except that the error it
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
877 signals is not continuable.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
878 @end defun
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 @defmac check-argument-type predicate argument
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
881 This macro checks that @var{argument} satisfies @var{predicate}. If
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
882 that is not the case, it signals a continuable
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
883 @code{wrong-type-argument} error until the returned value satisfies
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
884 @var{predicate}, and assigns the returned value to @var{argument}. In
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
885 other words, execution of the program will not continue until
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
886 @var{predicate} is met.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
887
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
888 @var{argument} is not evaluated, and should be a symbol.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
889 @var{predicate} is evaluated, and should name a function.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
890
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
891 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
892 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
893 proceeding.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
894
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
895 @example
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
896 @group
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
897 (defun cache-object-internal (object wlist)
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
898 ;; @r{Before doing anything, make sure that @var{wlist} is indeed}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
899 ;; @r{a weak list, which is what we expect.}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
900 (check-argument-type 'weak-list-p wlist)
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
901 @dots{})
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
902 @end group
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
903 @end example
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
904 @end defmac
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
905
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
906 @node Processing of Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
907 @subsubsection How XEmacs Processes Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
908
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
909 When an error is signaled, @code{signal} searches for an active
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
910 @dfn{handler} for the error. A handler is a sequence of Lisp
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
911 expressions designated to be executed if an error happens in part of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
912 Lisp program. If the error has an applicable handler, the handler is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
913 executed, and control resumes following the handler. The handler
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
914 executes in the environment of the @code{condition-case} that
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
915 established it; all functions called within that @code{condition-case}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
916 have already been exited, and the handler cannot return to them.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
917
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
918 If there is no applicable handler for the error, the current command is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
919 terminated and control returns to the editor command loop, because the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
920 command loop has an implicit handler for all kinds of errors. The
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
921 command loop's handler uses the error symbol and associated data to
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
922 print an error message.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
923
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
924 Errors in command loop are processed using the @code{command-error}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
925 function, which takes care of some necessary cleanup, and prints a
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
926 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
927 formatting are explained below.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
928
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
929 @defun display-error error-object stream
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
930 This function displays @var{error-object} on @var{stream}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
931 @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
932 arguments, a list. If the error type symbol of one of its error
901
37e56e920ac5 [xemacs-hg @ 2002-07-05 20:35:47 by adrian]
adrian
parents: 444
diff changeset
933 condition superclasses has a @code{display-error} property, that
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
934 function is invoked for printing the actual error message. Otherwise,
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
935 the error is printed as @samp{Error: arg1, arg2, ...}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
936 @end defun
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
937
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
938 @defun error-message-string error-object
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
939 This function converts @var{error-object} to an error message string,
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
940 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
941 printed by @code{display-error}, except that it is conveniently returned
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
942 in string form.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
943 @end defun
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
944
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
945 @cindex @code{debug-on-error} use
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
946 An error that has no explicit handler may call the Lisp debugger. The
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
947 debugger is enabled if the variable @code{debug-on-error} (@pxref{Error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
948 Debugging}) is non-@code{nil}. Unlike error handlers, the debugger runs
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
949 in the environment of the error, so that you can examine values of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
950 variables precisely as they were at the time of the error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
951
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
952 @node Handling Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
953 @subsubsection Writing Code to Handle Errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
954 @cindex error handler
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
955 @cindex handling errors
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
956
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
957 The usual effect of signaling an error is to terminate the command
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
958 that is running and return immediately to the XEmacs editor command loop.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
959 You can arrange to trap errors occurring in a part of your program by
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
960 establishing an error handler, with the special operator
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
961 @code{condition-case}. A simple example looks like this:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
962
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
963 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
964 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
965 (condition-case nil
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
966 (delete-file filename)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
967 (error nil))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
968 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
969 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
970
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
971 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
972 This deletes the file named @var{filename}, catching any error and
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
973 returning @code{nil} if an error occurs.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
974
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
975 The second argument of @code{condition-case} is called the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
976 @dfn{protected form}. (In the example above, the protected form is a
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
977 call to @code{delete-file}.) The error handlers go into effect when
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
978 this form begins execution and are deactivated when this form returns.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
979 They remain in effect for all the intervening time. In particular, they
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
980 are in effect during the execution of functions called by this form, in
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
981 their subroutines, and so on. This is a good thing, since, strictly
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
982 speaking, errors can be signaled only by Lisp primitives (including
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
983 @code{signal} and @code{error}) called by the protected form, not by the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
984 protected form itself.
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 arguments after the protected form are handlers. Each handler
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
987 lists one or more @dfn{condition names} (which are symbols) to specify
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
988 which errors it will handle. The error symbol specified when an error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
989 is signaled also defines a list of condition names. A handler applies
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
990 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
991 above, there is one handler, and it specifies one condition name,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
992 @code{error}, which covers all errors.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
993
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
994 The search for an applicable handler checks all the established handlers
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
995 starting with the most recently established one. Thus, if two nested
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
996 @code{condition-case} forms offer to handle the same error, the inner of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
997 the two will actually handle it.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
998
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
999 When an error is handled, control returns to the handler. Before this
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1000 happens, XEmacs unbinds all variable bindings made by binding constructs
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1001 that are being exited and executes the cleanups of all
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1002 @code{unwind-protect} forms that are exited. Once control arrives at
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1003 the handler, the body of the handler is executed.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1004
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1005 After execution of the handler body, execution continues by returning
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1006 from the @code{condition-case} form. Because the protected form is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1007 exited completely before execution of the handler, the handler cannot
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1008 resume execution at the point of the error, nor can it examine variable
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1009 bindings that were made within the protected form. All it can do is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1010 clean up and proceed.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1011
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1012 @code{condition-case} is often used to trap errors that are
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1013 predictable, such as failure to open a file in a call to
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1014 @code{insert-file-contents}. It is also used to trap errors that are
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1015 totally unpredictable, such as when the program evaluates an expression
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1016 read from the user.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1017
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1018 @cindex @code{debug-on-signal} use
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1019 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
1020 variable @code{debug-on-signal} (@pxref{Error Debugging}) is
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1021 non-@code{nil}. Note that this may yield unpredictable results with
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1022 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
1023 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
1024
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1025 Error signaling and handling have some resemblance to @code{throw} and
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1026 @code{catch}, but they are entirely separate facilities. An error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1027 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
1028 by an error handler (though using @code{throw} when there is no suitable
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1029 @code{catch} signals an error that can be handled).
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1030
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1031 @defspec condition-case var protected-form handlers@dots{}
4905
755ae5b97edb Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents: 2297
diff changeset
1032 This special operator establishes the error handlers @var{handlers} around
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1033 the execution of @var{protected-form}. If @var{protected-form} executes
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1034 without error, the value it returns becomes the value of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1035 @code{condition-case} form; in this case, the @code{condition-case} has
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1036 no effect. The @code{condition-case} form makes a difference when an
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1037 error occurs during @var{protected-form}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1038
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1039 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
1040 @var{body}@dots{})}. Here @var{conditions} is an error condition name
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1041 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
1042 Lisp expressions to be executed when this handler handles an error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1043 Here are examples of handlers:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1044
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1045 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1046 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1047 (error nil)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1048
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1049 (arith-error (message "Division by zero"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1050
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1051 ((arith-error file-error)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1052 (message
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1053 "Either division by zero or failure to open a file"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1054 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1055 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1056
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1057 Each error that occurs has an @dfn{error symbol} that describes what
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1058 kind of error it is. The @code{error-conditions} property of this
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1059 symbol is a list of condition names (@pxref{Error Symbols}). Emacs
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1060 searches all the active @code{condition-case} forms for a handler that
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1061 specifies one or more of these condition names; the innermost matching
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1062 @code{condition-case} handles the error. Within this
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1063 @code{condition-case}, the first applicable handler handles the error.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1064
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1065 After executing the body of the handler, the @code{condition-case}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1066 returns normally, using the value of the last form in the handler body
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1067 as the overall value.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1068
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1069 The argument @var{var} is a variable. @code{condition-case} does not
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1070 bind this variable when executing the @var{protected-form}, only when it
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1071 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
1072 the form @code{(@var{error-symbol} . @var{data})}, giving the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1073 particulars of the error. The handler can refer to this list to decide
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1074 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
1075 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
1076 @var{var}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1077
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1078 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
1079 error symbol and associated data are not available to the handler.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1080 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1081
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1082 @cindex @code{arith-error} example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1083 Here is an example of using @code{condition-case} to handle the error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1084 that results from dividing by zero. The handler prints out a warning
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1085 message and returns a very large number.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1086
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1087 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1088 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1089 (defun safe-divide (dividend divisor)
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
1090 (condition-case err
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1091 ;; @r{Protected form.}
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
1092 (/ dividend divisor)
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1093 ;; @r{The handler.}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1094 (arith-error ; @r{Condition.}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1095 (princ (format "Arithmetic error: %s" err))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1096 1000000)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1097 @result{} safe-divide
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1098 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1099
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1100 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1101 (safe-divide 5 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1102 @print{} Arithmetic error: (arith-error)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1103 @result{} 1000000
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1104 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1105 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1106
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1107 @noindent
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1108 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
1109 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
1110 handled, at least not by this @code{condition-case}. Thus,
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1111
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1112 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1113 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1114 (safe-divide nil 3)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1115 @error{} Wrong type argument: integer-or-marker-p, nil
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1116 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1117 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1118
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1119 Here is a @code{condition-case} that catches all kinds of errors,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1120 including those signaled with @code{error}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1121
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1122 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1123 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1124 (setq baz 34)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1125 @result{} 34
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1126 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1127
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1128 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1129 (condition-case err
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1130 (if (eq baz 35)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1131 t
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1132 ;; @r{This is a call to the function @code{error}.}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1133 (error "Rats! The variable %s was %s, not 35" 'baz baz))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1134 ;; @r{This is the handler; it is not a form.}
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
1135 (error (princ (format "The error was: %s" err))
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1136 2))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1137 @print{} The error was: (error "Rats! The variable baz was 34, not 35")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1138 @result{} 2
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1139 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1140 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1141
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1142 @node Error Symbols
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1143 @subsubsection Error Symbols and Condition Names
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1144 @cindex error symbol
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1145 @cindex error name
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1146 @cindex condition name
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1147 @cindex user-defined error
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1148 @kindex error-conditions
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1149
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1150 When you signal an error, you specify an @dfn{error symbol} to specify
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1151 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
1152 error symbol to categorize it. This is the finest classification of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1153 errors defined by the XEmacs Lisp language.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1154
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1155 These narrow classifications are grouped into a hierarchy of wider
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1156 classes called @dfn{error conditions}, identified by @dfn{condition
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1157 names}. The narrowest such classes belong to the error symbols
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1158 themselves: each error symbol is also a condition name. There are also
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1159 condition names for more extensive classes, up to the condition name
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1160 @code{error} which takes in all kinds of errors. Thus, each error has
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1161 one or more condition names: @code{error}, the error symbol if that
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1162 is distinct from @code{error}, and perhaps some intermediate
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1163 classifications.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1164
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1165 In other words, each error condition @dfn{inherits} from another error
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1166 condition, with @code{error} sitting at the top of the inheritance
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1167 hierarchy.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1168
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1169 @defun define-error error-symbol error-message &optional inherits-from
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1170 This function defines a new error, denoted by @var{error-symbol}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1171 @var{error-message} is an informative message explaining the error, and
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1172 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
1173 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
1174
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1175 @code{define-error} internally works by putting on @var{error-symbol}
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1176 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
1177 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
1178 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
1179 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
1180 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
1181 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
1182 provide @code{define-error}.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1183 @end defun
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1184
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1185 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
1186 belongs to a range of errors called @code{my-own-errors}:
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1187
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1188 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1189 @group
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1190 (define-error 'my-own-errors "A whole range of errors" 'error)
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1191 (define-error 'new-error "A new error" 'my-own-errors)
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1192 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1193 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1194
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1195 @noindent
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1196 @code{new-error} has three condition names: @code{new-error}, the
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1197 narrowest classification; @code{my-own-errors}, which we imagine is a
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1198 wider classification; and @code{error}, which is the widest of all.
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1199
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1200 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
1201 super-error is also defined. For instance, attempting to define
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1202 @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
1203 error.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1204
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1205 The error string should start with a capital letter but it should
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1206 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
1207
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1208 Naturally, XEmacs will never signal @code{new-error} on its own; only
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1209 an explicit call to @code{signal} (@pxref{Signaling Errors}) in your
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1210 code can do this:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1211
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1212 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1213 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1214 (signal 'new-error '(x y))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1215 @error{} A new error: x, y
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1216 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1217 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1218
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1219 This error can be handled through any of the three condition names.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1220 This example handles @code{new-error} and any other errors in the class
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1221 @code{my-own-errors}:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1222
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1223 @example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1224 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1225 (condition-case foo
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1226 (bar nil t)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1227 (my-own-errors nil))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1228 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1229 @end example
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1230
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1231 The significant way that errors are classified is by their condition
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1232 names---the names used to match errors with handlers. An error symbol
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1233 serves only as a convenient way to specify the intended error message
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1234 and list of condition names. It would be cumbersome to give
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1235 @code{signal} a list of condition names rather than one error symbol.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1236
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1237 By contrast, using only error symbols without condition names would
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1238 seriously decrease the power of @code{condition-case}. Condition names
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1239 make it possible to categorize errors at various levels of generality
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1240 when you write an error handler. Using error symbols alone would
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1241 eliminate all but the narrowest level of classification.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1242
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 398
diff changeset
1243
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 0
diff changeset
1244
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1245 @xref{Standard Errors}, for a list of all the standard error symbols
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1246 and their conditions.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1247
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1248 @node Cleanups
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1249 @subsection Cleaning Up from Nonlocal Exits
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1250
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1251 The @code{unwind-protect} construct is essential whenever you
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1252 temporarily put a data structure in an inconsistent state; it permits
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1253 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
1254
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1255 @defspec unwind-protect body cleanup-forms@dots{}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1256 @cindex cleanup forms
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1257 @cindex protected forms
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1258 @cindex error cleanup
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1259 @cindex unwinding
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1260 @code{unwind-protect} executes the @var{body} with a guarantee that the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1261 @var{cleanup-forms} will be evaluated if control leaves @var{body}, no
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1262 matter how that happens. The @var{body} may complete normally, or
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1263 execute a @code{throw} out of the @code{unwind-protect}, or cause an
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1264 error; in all cases, the @var{cleanup-forms} will be evaluated.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1265
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1266 If the @var{body} forms finish normally, @code{unwind-protect} returns
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1267 the value of the last @var{body} form, after it evaluates the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1268 @var{cleanup-forms}. If the @var{body} forms do not finish,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1269 @code{unwind-protect} does not return any value in the normal sense.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1270
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1271 Only the @var{body} is actually protected by the @code{unwind-protect}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1272 If any of the @var{cleanup-forms} themselves exits nonlocally (e.g., via
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1273 a @code{throw} or an error), @code{unwind-protect} is @emph{not}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1274 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
1275 @var{cleanup-forms} has the potential to cause trouble, then protect it
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1276 with another @code{unwind-protect} around that form.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1277
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1278 The number of currently active @code{unwind-protect} forms counts,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1279 together with the number of local variable bindings, against the limit
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1280 @code{max-specpdl-size} (@pxref{Local Variables}).
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1281 @end defspec
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1282
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1283 For example, here we make an invisible buffer for temporary use, and
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1284 make sure to kill it before finishing:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1285
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1286 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1287 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1288 (save-excursion
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1289 (let ((buffer (get-buffer-create " *temp*")))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1290 (set-buffer buffer)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1291 (unwind-protect
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1292 @var{body}
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1293 (kill-buffer buffer))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1294 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1295 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1296
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1297 @noindent
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1298 You might think that we could just as well write @code{(kill-buffer
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1299 (current-buffer))} and dispense with the variable @code{buffer}.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1300 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
1301 error after switching to a different buffer! (Alternatively, you could
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1302 write another @code{save-excursion} around the body, to ensure that the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1303 temporary buffer becomes current in time to kill it.)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1304
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1305 @findex ftp-login
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1306 Here is an actual example taken from the file @file{ftp.el}. It
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1307 creates a process (@pxref{Processes}) to try to establish a connection
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1308 to a remote machine. As the function @code{ftp-login} is highly
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1309 susceptible to numerous problems that the writer of the function cannot
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1310 anticipate, it is protected with a form that guarantees deletion of the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1311 process in the event of failure. Otherwise, XEmacs might fill up with
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1312 useless subprocesses.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1313
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1314 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1315 @group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1316 (let ((win nil))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1317 (unwind-protect
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1318 (progn
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1319 (setq process (ftp-setup-buffer host file))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1320 (if (setq win (ftp-login process host user password))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1321 (message "Logged in")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1322 (error "Ftp login failed")))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1323 (or win (and process (delete-process process)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1324 @end group
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1325 @end smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1326
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1327 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
1328 quit, and the quit happens immediately after the function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1329 @code{ftp-setup-buffer} returns but before the variable @code{process} is
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1330 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
1331 but at least it is very unlikely.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1332
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1333 Here is another example which uses @code{unwind-protect} to make sure
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1334 to kill a temporary buffer. In this example, the value returned by
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1335 @code{unwind-protect} is used.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1336
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1337 @smallexample
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1338 (defun shell-command-string (cmd)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1339 "Return the output of the shell command CMD, as a string."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1340 (save-excursion
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1341 (set-buffer (generate-new-buffer " OS*cmd"))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1342 (shell-command cmd t)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1343 (unwind-protect
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1344 (buffer-string)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1345 (kill-buffer (current-buffer)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1346 @end smallexample