1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-09 21:40:33 +02:00

* Extended documentation on exceptions.

* Minor changes to Martin's doc on continuations.
This commit is contained in:
Neil Jerram 2001-04-22 13:15:42 +00:00
parent 7a7f7c5314
commit 006064cefe
2 changed files with 126 additions and 18 deletions

View file

@ -1,3 +1,9 @@
2001-04-22 Neil Jerram <neil@ossau.uklinux.net>
* scheme-control.texi (Exceptions): Extended documentation.
(Continuations): Correct "except" typo, and fix reference to
Exceptions node. Plus minor review changes.
2001-04-20 Neil Jerram <neil@ossau.uklinux.net> 2001-04-20 Neil Jerram <neil@ossau.uklinux.net>
* scheme-control.texi (Exceptions): Reorganized and extended * scheme-control.texi (Exceptions): Reorganized and extended

View file

@ -249,25 +249,27 @@ times.
@node Continuations @node Continuations
@section Continuations @section Continuations
@c FIXME::martin: Review me!
@cindex call/cc @cindex call/cc
The possibility to explicitly capture continuation and the use of @cindex call-with-current-continuation
The ability to explicitly capture continuations using
@code{call-with-current-continuation} (also often called @code{call/cc} @code{call-with-current-continuation} (also often called @code{call/cc}
for shortness) is maybe the most powerful control structure known. All for short), and to invoke such continuations later any number of times,
other control structures like loops or coroutines can be emulated using and from any other point in a program, provides maybe the most powerful
continuation. control structure known. All other control structures, such as loops
and coroutines, can be emulated using continuations.
@c NJFIXME - need a little something here about what continuations are
@c and what they do for you.
@c FIXME::martin: Is this too much of understatement, maybe confusing?
@c I'm not sure.
The implementation of continuations in Guile is not as efficient as one The implementation of continuations in Guile is not as efficient as one
might except, because it is constrained by the fact that Guile is might hope, because it is constrained by the fact that Guile is designed
required to be cooperative to programs written in other languages, such to cooperate with programs written in other languages, such as C, which
as C which do not know about continuations. So continuations should be do not know about continuations. So continuations should be used when
used when there is no other possibility to get the needed effect. If there is no other simple way of achieving the desired behaviour, or
you find yourself using @code{call/cc} for escape procedures and your where the advantages of the elegant continuation mechanism outweigh the
program is running to slow, you might want to use exceptions (REFFIXME) need for optimum performance. If you find yourself using @code{call/cc}
instead. for escape procedures and your program is running too slow, you might
want to use exceptions (@pxref{Exceptions}) instead.
@rnindex call-with-current-continuation @rnindex call-with-current-continuation
@deffn primitive call-with-current-continuation proc @deffn primitive call-with-current-continuation proc
@ -404,15 +406,89 @@ programming languages) provides an additional mechanism called
more conveniently. more conveniently.
@menu @menu
* Catch and Throw:: Basic exception handling primitives. * Exception Terminology:: Different ways to say the same thing.
* Catch:: Setting up to catch exceptions.
* Throw:: Throwing an exception.
* Lazy Catch:: Catch without unwinding. * Lazy Catch:: Catch without unwinding.
* Stack Catch:: Capturing the stack at a throw. * Stack Catch:: Capturing the stack at a throw.
* Exception Implementation:: How Guile implements exceptions. * Exception Implementation:: How Guile implements exceptions.
@end menu @end menu
@node Catch and Throw @node Exception Terminology
@subsection Basic Exception Handling Primitives @subsection Exception Terminology
There are several variations on the terminology for dealing with
non-local jumps. It is useful to be aware of them, and to realize
that they all refer to the same basic mechanism.
@itemize @bullet
@item
Actually making a non-local jump may be called @dfn{raising an
exception}, @dfn{raising a signal}, @dfn{throwing an exception} or
@dfn{doing a long jump}. When the jump indicates an error condition,
people may talk about @dfn{signalling}, @dfn{raising} or @dfn{throwing}
@dfn{an error}.
@item
Handling the jump at its target may be referred to as @dfn{catching} or
@dfn{handling} the @dfn{exception}, @dfn{signal} or, where an error
condition is involved, @dfn{error}.
@end itemize
Where @dfn{signal} and @dfn{signalling} are used, special care is needed
to avoid the risk of confusion with POSIX signals. (Especially
considering that Guile handles POSIX signals by throwing a corresponding
kind of exception: REFFIXME.)
This manual prefers to speak of throwing and catching exceptions, since
this terminology matches the corresponding Guile primitives.
@node Catch
@subsection Catching Exceptions
@code{catch} is used to set up a target for a possible non-local jump.
The arguments of a @code{catch} expression are a @dfn{key}, which
restricts the set of exceptions to which this @code{catch} applies, a
thunk that specifies the @dfn{normal case} code --- i.e. what should
happen if no exceptions are thrown --- and a @dfn{handler} procedure
that says what to do if an exception is thrown. Note that if the
@dfn{normal case} thunk executes @dfn{normally}, which means without
throwing any exceptions, the handler procedure is not executed at all.
When an exception is thrown using the @code{throw} primitive, the first
argument of the @code{throw} is a symbol that indicates the type of the
exception. For example, Guile throws an exception using the symbol
@code{numerical-overflow} to indicate numerical overflow errors such as
division by zero:
@lisp
(/ 1 0)
@result{}
ABORT: (numerical-overflow)
@end lisp
The @var{key} argument in a @code{catch} expression corresponds to this
symbol. @var{key} may be a specific symbol, such as
@code{numerical-overflow}, in which case the @code{catch} applies
specifically to exceptions of that type; or it may be @code{#t}, which
means that the @code{catch} applies to all exceptions, irrespective of
their type.
The second argument of a @code{catch} expression should be a thunk
(i.e. a procedure that accepts no arguments) that specifies the normal
case code. The @code{catch} is active for the execution of this thunk,
including any code called directly or indirectly by the thunk's body.
Evaluation of the @code{catch} expression activates the catch and then
calls this thunk.
The third argument of a @code{catch} expression is a handler procedure.
If an exception is thrown, this procedure is called with exactly the
arguments specified by the @code{throw}. Therefore, the handler
procedure must be designed to accept a number of arguments that
corresponds to the number of arguments in all @code{throw} expressions
that can be caught by this @code{catch}.
@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
@ -431,6 +507,32 @@ If the key is @code{#t}, then a throw to @emph{any} symbol will
match this call to @code{catch}. match this call to @code{catch}.
@end deffn @end deffn
If the handler procedure needs to match a variety of @code{throw}
expressions with varying numbers of arguments, you should write it like
this:
@lisp
(lambda (key . args)
@dots{})
@end lisp
@noindent
The @var{key} argument is guaranteed always to be present, because a
@code{throw} without a @var{key} is not valid. The number and
interpretation of the @var{args} varies from one type of exception to
another, but should be specified by the documentation for each exception
type.
Note that, once the handler procedure is invoked, the catch that led to
the handler procedure being called is no longer active. Therefore, if
the handler procedure itself throws an exception, that exception can
only be caught by another active catch higher up the call stack, if
there is one.
@node Throw
@subsection Throwing Exceptions
@deffn primitive throw key . args @deffn primitive throw key . args
Invoke the catch form matching @var{key}, passing @var{args} to the Invoke the catch form matching @var{key}, passing @var{args} to the
@var{handler}. @var{handler}.