-\1f
-File: lispref.info, Node: Handling Errors, Next: Error Symbols, Prev: Processing of Errors, Up: Errors
-
-Writing Code to Handle Errors
-.............................
-
- The usual effect of signaling an error is to terminate the command
-that is running and return immediately to the XEmacs 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, XEmacs 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' (*note 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).
-
- - Special Form: condition-case var protected-form handlers...
- 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 (*note Error Symbols::). Emacs
- 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
-