1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-12 23:00:22 +02:00

* Improve doc for exceptions.

This commit is contained in:
Neil Jerram 2001-04-20 15:59:30 +00:00
parent ee75653426
commit 0447f5c918
2 changed files with 85 additions and 12 deletions

View file

@ -1,3 +1,8 @@
2001-04-20 Neil Jerram <neil@ossau.uklinux.net>
* scheme-control.texi (Exceptions): Reorganized and extended
existing documentation; more to come.
2001-04-20 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> 2001-04-20 Martin Grabmueller <mgrabmue@cs.tu-berlin.de>
* scheme-evaluation.texi (Comments): Document normal comments and * scheme-evaluation.texi (Comments): Document normal comments and

View file

@ -372,17 +372,47 @@ the expressions in @var{body} @dots{} are evaluated in order.
@cindex error handling @cindex error handling
@cindex exception handling @cindex exception handling
It is traditional in Scheme to implement exception systems using A common requirement in applications is to want to jump
@code{call-with-current-continuation} (@pxref{Continuations}). Guile @dfn{non-locally} from the depths of a computation back to, say, the
does not do this, for performance reasons. The implementation of application's main processing loop. Usually, the place that is the
@code{call-with-current-continuation} is a stack copying implementation. target of the jump is somewhere in the calling stack of procedures that
This allows it to interact well with ordinary C code. Unfortunately, a called the procedure that wants to jump back. For example, typical
stack-copying implementation can be slow -- creating a new continuation logic for a key press driven application might look something like this:
involves a block copy of the stack.
Instead of using @code{call-with-current-continuation}, the exception @example
primitives documented here are implemented as built-ins that take main-loop:
advantage of the @emph{upward only} nature of exceptions. read the next key press and call dispatch-key
dispatch-key:
lookup the key in a keymap and call an appropriate procedure,
say find-file
find-file:
interactively read the required file name, then call
find-specified-file
find-specified-file:
check whether file exists; if not, jump back to main-loop
@dots{}
@end example
The jump back to @code{main-loop} could be achieved by returning through
the stack one procedure at a time, using the return value of each
procedure to indicate the error condition, but Guile (like most modern
programming languages) provides an additional mechanism called
@dfn{exception handling} that can be used to implement such jumps much
more conveniently.
@menu
* Catch and Throw:: Basic exception handling primitives.
* Lazy Catch:: Catch without unwinding.
* Stack Catch:: Capturing the stack at a throw.
* Exception Implementation:: How Guile implements exceptions.
@end menu
@node Catch and Throw
@subsection Basic Exception Handling Primitives
@deffn primitive catch key thunk handler @deffn primitive catch key thunk handler
Invoke @var{thunk} in the dynamic context of @var{handler} for Invoke @var{thunk} in the dynamic context of @var{handler} for
@ -411,6 +441,10 @@ Invoke the catch form matching @var{key}, passing @var{args} to the
If there is no handler at all, an error is signaled. If there is no handler at all, an error is signaled.
@end deffn @end deffn
@node Lazy Catch
@subsection Catch Without Unwinding
@deffn primitive lazy-catch key thunk handler @deffn primitive lazy-catch key thunk handler
This behaves exactly like @code{catch}, except that it does This behaves exactly like @code{catch}, except that it does
not unwind the stack (this is the major difference), and if not unwind the stack (this is the major difference), and if
@ -418,6 +452,42 @@ handler returns, its value is returned from the throw.
@end deffn @end deffn
@node Stack Catch
@subsection Capturing the Stack at a Throw
@node Exception Implementation
@subsection How Guile Implements Exceptions
It is traditional in Scheme to implement exception systems using
@code{call-with-current-continuation}. Continuations
(@pxref{Continuations}) are such a powerful concept that any other
control mechanism --- including @code{catch} and @code{throw} --- can be
implemented in terms of them.
Guile does not implement @code{catch} and @code{throw} like this,
though. Why not? Because Guile is specifically designed to be easy to
integrate with applications written in C. In a mixed Scheme/C
environment, the concept of @dfn{continuation} must logically include
``what happens next'' in the C parts of the application as well as the
Scheme parts, and it turns out that the only reasonable way of
implementing continuations like this is to save and restore the complete
C stack.
So Guile's implementation of @code{call-with-current-continuation} is a
stack copying one. This allows it to interact well with ordinary C
code, but means that creating and calling a continuation is slowed down
by the time that it takes to copy the C stack.
The more targeted mechanism provided by @code{catch} and @code{throw}
does not need to save and restore the C stack because the @code{throw}
always jumps to a location higher up the stack of the code that executes
the @code{throw}. Therefore Guile implements the @code{catch} and
@code{throw} primitives independently of
@code{call-with-current-continuation}, in a way that takes advantage of
this @emph{upwards only} nature of exceptions.
@node Error Reporting @node Error Reporting
@section Procedures for Signaling Errors @section Procedures for Signaling Errors
@ -425,12 +495,10 @@ Guile provides a set of convenience procedures for signaling error
conditions that are implemented on top of the exception primitives just conditions that are implemented on top of the exception primitives just
described. described.
@c begin (scm-doc-string "boot-9.scm" "error")
@deffn procedure error msg args @dots{} @deffn procedure error msg args @dots{}
Raise an error with key @code{misc-error} and a message constructed by Raise an error with key @code{misc-error} and a message constructed by
displaying @var{msg} and writing @var{args}. displaying @var{msg} and writing @var{args}.
@end deffn @end deffn
@c end
@deffn primitive scm-error key subr message args data @deffn primitive scm-error key subr message args data
Raise an error with key @var{key}. @var{subr} can be a string Raise an error with key @var{key}. @var{subr} can be a string