1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-11 22:31:12 +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>
* 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 exception handling
It is traditional in Scheme to implement exception systems using
@code{call-with-current-continuation} (@pxref{Continuations}). Guile
does not do this, for performance reasons. The implementation of
@code{call-with-current-continuation} is a stack copying implementation.
This allows it to interact well with ordinary C code. Unfortunately, a
stack-copying implementation can be slow -- creating a new continuation
involves a block copy of the stack.
A common requirement in applications is to want to jump
@dfn{non-locally} from the depths of a computation back to, say, the
application's main processing loop. Usually, the place that is the
target of the jump is somewhere in the calling stack of procedures that
called the procedure that wants to jump back. For example, typical
logic for a key press driven application might look something like this:
Instead of using @code{call-with-current-continuation}, the exception
primitives documented here are implemented as built-ins that take
advantage of the @emph{upward only} nature of exceptions.
@example
main-loop:
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
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.
@end deffn
@node Lazy Catch
@subsection Catch Without Unwinding
@deffn primitive lazy-catch key thunk handler
This behaves exactly like @code{catch}, except that it does
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
@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
@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
described.
@c begin (scm-doc-string "boot-9.scm" "error")
@deffn procedure error msg args @dots{}
Raise an error with key @code{misc-error} and a message constructed by
displaying @var{msg} and writing @var{args}.
@end deffn
@c end
@deffn primitive scm-error key subr message args data
Raise an error with key @var{key}. @var{subr} can be a string