Next: Error Symbols, Previous: Processing of Errors, Up: Errors [Contents][Index]
The usual effect of signaling an error is to terminate the command
that is running and return immediately to the SXEmacs editor command
loop. You can arrange to trap errors occurring in a part of your program
by establishing an error handler, with the special form
condition-case
. A simple example looks like this:
(condition-case nil (delete-file filename) (error nil))
This deletes the file named filename, catching any error and
returning nil
if an error occurs.
The second argument of condition-case
is called the
protected form. (In the example above, the protected form is a
call to delete-file
.) The error handlers go into effect when
this form begins execution and are deactivated when this form returns.
They remain in effect for all the intervening time.
In particular, they are in effect during the execution of functions
called by this form, in their subroutines, and so on. This is a good
thing, since, strictly speaking, errors can be signaled only by Lisp
primitives (including signal
and error
) called by the
protected form, not by the protected form itself.
The arguments after the protected form are handlers. Each handler
lists one or more condition names (which are symbols) to specify
which errors it will handle. The error symbol specified when an error
is signaled also defines a list of condition names. A handler applies
to an error if they have any condition names in common. In the example
above, there is one handler, and it specifies one condition name,
error
, which covers all errors.
The search for an applicable handler checks all the established handlers
starting with the most recently established one. Thus, if two nested
condition-case
forms offer to handle the same error, the inner of
the two will actually handle it.
When an error is handled, control returns to the handler. Before this
happens, SXEmacs unbinds all variable bindings made by binding
constructs that are being exited and executes the cleanups of all
unwind-protect
forms that are exited. Once control arrives at
the handler, the body of the handler is executed.
After execution of the handler body, execution continues by returning
from the condition-case
form. Because the protected form is
exited completely before execution of the handler, the handler cannot
resume execution at the point of the error, nor can it examine variable
bindings that were made within the protected form. All it can do is
clean up and proceed.
condition-case
is often used to trap errors that are
predictable, such as failure to open a file in a call to
insert-file-contents
. It is also used to trap errors that are
totally unpredictable, such as when the program evaluates an expression
read from the user.
Even when an error is handled, the debugger may still be called if the
variable debug-on-signal
(see Error Debugging) is
non-nil
. Note that this may yield unpredictable results with
code that traps expected errors as normal part of its operation. Do not
set debug-on-signal
unless you know what you are doing.
Error signaling and handling have some resemblance to throw
and
catch
, but they are entirely separate facilities. An error
cannot be caught by a catch
, and a throw
cannot be handled
by an error handler (though using throw
when there is no suitable
catch
signals an error that can be handled).
This special form establishes the error handlers handlers around
the execution of protected-form. If protected-form executes
without error, the value it returns becomes the value of the
condition-case
form; in this case, the condition-case
has
no effect. The condition-case
form makes a difference when an
error occurs during protected-form.
Each of the handlers is a list of the form (conditions
body…)
. Here conditions is an error condition name
to be handled, or a list of condition names; body is one or more
Lisp expressions to be executed when this handler handles an error.
Here are examples of handlers:
(error nil) (arith-error (message "Division by zero")) ((arith-error file-error) (message "Either division by zero or failure to open a file"))
Each error that occurs has an error symbol that describes what
kind of error it is. The error-conditions
property of this
symbol is a list of condition names (see Error Symbols). SXEmacs
searches all the active condition-case
forms for a handler that
specifies one or more of these condition names; the innermost matching
condition-case
handles the error. Within this
condition-case
, the first applicable handler handles the error.
After executing the body of the handler, the condition-case
returns normally, using the value of the last form in the handler body
as the overall value.
The argument var is a variable. condition-case
does not
bind this variable when executing the protected-form, only when it
handles an error. At that time, it binds var locally to a list of
the form (error-symbol . data)
, giving the
particulars of the error. The handler can refer to this list to decide
what to do. For example, if the error is for failure opening a file,
the file name is the second element of data—the third element of
var.
If var is nil
, that means no variable is bound. Then the
error symbol and associated data are not available to the handler.
Here is an example of using condition-case
to handle the error
that results from dividing by zero. The handler prints out a warning
message and returns a very large number.
(defun safe-divide (dividend divisor) (condition-case err ;; Protected form. (/ dividend divisor) ;; The handler. (arith-error ; Condition. (princ (format "Arithmetic error: %s" err)) 1000000))) ⇒ safe-divide
(safe-divide 5 0) -| Arithmetic error: (arith-error) ⇒ 1000000
The handler specifies condition name arith-error
so that it will
handle only division-by-zero errors. Other kinds of errors will not be
handled, at least not by this condition-case
. Thus,
(safe-divide nil 3) error→ Wrong type argument: integer-or-marker-p, nil
Here is a condition-case
that catches all kinds of errors,
including those signaled with error
:
(setq baz 34) ⇒ 34
(condition-case err
(if (eq baz 35)
t
;; This is a call to the function error
.
(error "Rats! The variable %s was %s, not 35" 'baz baz))
;; This is the handler; it is not a form.
(error (princ (format "The error was: %s" err))
2))
-| The error was: (error "Rats! The variable baz was 34, not 35")
⇒ 2
Next: Error Symbols, Previous: Processing of Errors, Up: Errors [Contents][Index]