aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2024-01-04 16:28:39 -0500
committerStefan Monnier2024-01-04 16:39:48 -0500
commitae75333ca78f5c45e53e7e5d25f4e04a4d69ad8f (patch)
tree95bc5483e0fb5a979118ec85821c543582dc9e44
parent391c208aecc44fd82c599696d47a18782f2f36da (diff)
downloademacs-ae75333ca78f5c45e53e7e5d25f4e04a4d69ad8f.tar.gz
emacs-ae75333ca78f5c45e53e7e5d25f4e04a4d69ad8f.zip
Improve `handler-bind` doc
* doc/lispref/control.texi (Handling Errors) <handler-bind>: Expand. * doc/lispref/variables.texi (Variable Scoping): Mention static scoping.
-rw-r--r--doc/lispref/control.texi102
-rw-r--r--doc/lispref/variables.texi4
2 files changed, 93 insertions, 13 deletions
diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 6cc25dcdaee..3c9f26262c1 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -1,6 +1,6 @@
1@c -*- mode: texinfo; coding: utf-8 -*- 1@c -*- mode: texinfo; coding: utf-8 -*-
2@c This is part of the GNU Emacs Lisp Reference Manual. 2@c This is part of the GNU Emacs Lisp Reference Manual.
3@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software 3@c Copyright (C) 1990--2024 Free Software
4@c Foundation, Inc. 4@c Foundation, Inc.
5@c See the file elisp.texi for copying conditions. 5@c See the file elisp.texi for copying conditions.
6@node Control Structures 6@node Control Structures
@@ -2311,24 +2311,102 @@ form. In this case, the @code{handler-bind} has no effect.
2311@code{(@var{conditions} @var{handler})} where @var{conditions} is an 2311@code{(@var{conditions} @var{handler})} where @var{conditions} is an
2312error condition name to be handled, or a list of condition names, and 2312error condition name to be handled, or a list of condition names, and
2313@var{handler} should be a form whose evaluation should return a function. 2313@var{handler} should be a form whose evaluation should return a function.
2314As with @code{condition-case}, condition names are symbols.
2314 2315
2315Before running @var{body}, @code{handler-bind} evaluates all the 2316Before running @var{body}, @code{handler-bind} evaluates all the
2316@var{handler} forms and installs those handlers to be active during 2317@var{handler} forms and installs those handlers to be active during
2317the evaluation of @var{body}. These handlers are searched together 2318the evaluation of @var{body}. When an error is signaled,
2318with those installed by @code{condition-case}. When the innermost 2319Emacs searches all the active @code{condition-case} and
2320@code{handler-bind} forms for a handler that
2321specifies one or more of these condition names. When the innermost
2319matching handler is one installed by @code{handler-bind}, the 2322matching handler is one installed by @code{handler-bind}, the
2320@var{handler} function is called with a single argument holding the 2323@var{handler} function is called with a single argument holding the
2321error description. 2324error description.
2322 2325
2323@var{handler} is called in the dynamic context where the error 2326Contrary to what happens with @code{condition-case}, @var{handler} is
2324happened, without first unwinding the stack, meaning that all the 2327called in the dynamic context where the error happened. This means it
2325dynamic bindings are still in effect, except that all the error 2328is executed unbinding any variable bindings or running any cleanups of
2326handlers between the code that signaled the error and the 2329@code{unwind-protect}, so that all those dynamic bindings are still in
2327@code{handler-bind} are temporarily suspended. Like any normal 2330effect. There is one exception: while running the @var{handler}
2328function, @var{handler} can exit non-locally, typically via 2331function, all the error handlers between the code that signaled the
2329@code{throw}, or it can return normally. If @var{handler} returns 2332error and the @code{handler-bind} are temporarily suspended, meaning
2330normally, it means the handler @emph{declined} to handle the error and 2333that when an error is signaled, Emacs will only search the active
2331the search for an error handler is continued where it left off. 2334@code{condition-case} and @code{handler-bind} forms that are inside
2335the @var{handler} function or outside of the current
2336@code{handler-bind}. Note also that lexical variables are not
2337affected, since they do not have dynamic extent.
2338
2339Like any normal function, @var{handler} can exit non-locally,
2340typically via @code{throw}, or it can return normally.
2341If @var{handler} returns normally, it means the handler
2342@emph{declined} to handle the error and the search for an error
2343handler is continued where it left off.
2344
2345For example, if we wanted to keep a log of all the errors that occur
2346during the execution of a particular piece of code together with the
2347buffer that's current when the error is signaled, but without
2348otherwise affecting the behavior of that code, we can do it with:
2349
2350@example
2351@group
2352(handler-bind
2353 ((error
2354 (lambda (err)
2355 (push (cons err (current-buffer)) my-log-of-errors))))
2356 @var{body-forms}@dots{})
2357@end group
2358@end example
2359
2360This will log only those errors that are not caught internally to
2361@var{body-forms}@dots{}, in other words errors that ``escape'' from
2362@var{body-forms}@dots{}, and it will not prevent those errors from
2363being passed on to surrounding @code{condition-case} handlers (or
2364@code{handler-bind} handlers for that matter) since the above handler
2365returns normally.
2366
2367We can also use @code{handler-bind} to replace an error with another,
2368as in the code below which turns all errors of type @code{user-error}
2369that occur during the execution of @var{body-forms}@dots{} into plain
2370@code{error}:
2371
2372@example
2373@group
2374(handler-bind
2375 ((user-error
2376 (lambda (err)
2377 (signal 'error (cdr err)))))
2378 @var{body-forms}@dots{})
2379@end group
2380@end example
2381
2382We can get almost the same result with @code{condition-case}:
2383
2384@example
2385@group
2386(condition-case err
2387 (progn @var{body-forms}@dots{})
2388 (user-error (signal 'error (cdr err))))
2389@end group
2390@end example
2391
2392@noindent
2393but with the difference that when we (re)signal the new error in
2394@code{handler-bind} the dynamic environment from the original error is
2395still active, which means for example that if we enter the
2396debugger at this point, it will show us a complete backtrace including
2397the point where we signaled the original error:
2398
2399@example
2400@group
2401Debugger entered--Lisp error: (error "Oops")
2402 signal(error ("Oops"))
2403 (closure (t) (err) (signal 'error (cdr err)))((user-error "Oops"))
2404 user-error("Oops")
2405 @dots{}
2406 eval((handler-bind ((user-error (lambda (err) @dots{}
2407@end group
2408@end example
2409
2332@end defmac 2410@end defmac
2333 2411
2334@node Error Symbols 2412@node Error Symbols
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 705d3260063..4d61d461deb 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -1,6 +1,6 @@
1@c -*-texinfo-*- 1@c -*-texinfo-*-
2@c This is part of the GNU Emacs Lisp Reference Manual. 2@c This is part of the GNU Emacs Lisp Reference Manual.
3@c Copyright (C) 1990--1995, 1998--2024 Free Software Foundation, Inc. 3@c Copyright (C) 1990--2024 Free Software Foundation, Inc.
4@c See the file elisp.texi for copying conditions. 4@c See the file elisp.texi for copying conditions.
5@node Variables 5@node Variables
6@chapter Variables 6@chapter Variables
@@ -978,6 +978,7 @@ program is executing, the binding exists.
978 978
979@cindex lexical binding 979@cindex lexical binding
980@cindex lexical scope 980@cindex lexical scope
981@cindex static scope
981@cindex indefinite extent 982@cindex indefinite extent
982 For historical reasons, there are two dialects of Emacs Lisp, 983 For historical reasons, there are two dialects of Emacs Lisp,
983selected via the @code{lexical-binding} buffer-local variable. 984selected via the @code{lexical-binding} buffer-local variable.
@@ -989,6 +990,7 @@ binding can also be accessed from the Lisp debugger.}. It also has
989@dfn{indefinite extent}, meaning that under some circumstances the 990@dfn{indefinite extent}, meaning that under some circumstances the
990binding can live on even after the binding construct has finished 991binding can live on even after the binding construct has finished
991executing, by means of objects called @dfn{closures}. 992executing, by means of objects called @dfn{closures}.
993Lexical scoping is also commonly called @dfn{static scoping}.
992 994
993@cindex dynamic binding 995@cindex dynamic binding
994@cindex dynamic scope 996@cindex dynamic scope