mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-12 23:00:22 +02:00
(Throw Handlers): New node.
(Throw): Moved to after the Lazy Catch node. (Catch): Enhance to cover the optional pre-unwind handler, and new APIs scm_c_catch, scm_catch_with_pre_unwind_handler. (Lazy Catch): Describe relationship to with-throw-handler. Document that the handler may return, and what happens if it does. (Throw): Mention that a throw can be handled by a throw handler as well as by a catch.
This commit is contained in:
parent
ba28d59428
commit
7b4c914e49
2 changed files with 228 additions and 86 deletions
|
@ -1,3 +1,14 @@
|
||||||
|
2006-02-04 Neil Jerram <neil@ossau.uklinux.net>
|
||||||
|
|
||||||
|
* api-control.texi (Throw Handlers): New node.
|
||||||
|
(Throw): Moved to after the Lazy Catch node.
|
||||||
|
(Catch): Enhance to cover the optional pre-unwind handler, and new
|
||||||
|
APIs scm_c_catch, scm_catch_with_pre_unwind_handler.
|
||||||
|
(Lazy Catch): Describe relationship to with-throw-handler.
|
||||||
|
Document that the handler may return, and what happens if it does.
|
||||||
|
(Throw): Mention that a throw can be handled by a throw handler as
|
||||||
|
well as by a catch.
|
||||||
|
|
||||||
2006-02-04 Kevin Ryde <user42@zip.com.au>
|
2006-02-04 Kevin Ryde <user42@zip.com.au>
|
||||||
|
|
||||||
* api-options.texi (Build Config): pxref libtool on libguileinterface
|
* api-options.texi (Build Config): pxref libtool on libguileinterface
|
||||||
|
|
|
@ -600,8 +600,9 @@ more conveniently.
|
||||||
@menu
|
@menu
|
||||||
* Exception Terminology:: Different ways to say the same thing.
|
* Exception Terminology:: Different ways to say the same thing.
|
||||||
* Catch:: Setting up to catch exceptions.
|
* Catch:: Setting up to catch exceptions.
|
||||||
* Throw:: Throwing an exception.
|
* Throw Handlers:: Adding extra handling to a throw.
|
||||||
* Lazy Catch:: Catch without unwinding the stack.
|
* Lazy Catch:: Catch without unwinding the stack.
|
||||||
|
* Throw:: Throwing an exception.
|
||||||
* Exception Implementation:: How Guile implements exceptions.
|
* Exception Implementation:: How Guile implements exceptions.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
@ -640,11 +641,11 @@ this terminology matches the corresponding Guile primitives.
|
||||||
@code{catch} is used to set up a target for a possible non-local jump.
|
@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
|
The arguments of a @code{catch} expression are a @dfn{key}, which
|
||||||
restricts the set of exceptions to which this @code{catch} applies, a
|
restricts the set of exceptions to which this @code{catch} applies, a
|
||||||
thunk that specifies the code to execute and a @dfn{handler} procedure
|
thunk that specifies the code to execute and one or two @dfn{handler}
|
||||||
that says what to do if an exception is thrown while executing the code.
|
procedures that say what to do if an exception is thrown while executing
|
||||||
Note that if the execution thunk executes @dfn{normally}, which means
|
the code. If the execution thunk executes @dfn{normally}, which means
|
||||||
without throwing any exceptions, the handler procedure is not called at
|
without throwing any exceptions, the handler procedures are not called
|
||||||
all.
|
at all.
|
||||||
|
|
||||||
When an exception is thrown using the @code{throw} function, the first
|
When an exception is thrown using the @code{throw} function, the first
|
||||||
argument of the @code{throw} is a symbol that indicates the type of the
|
argument of the @code{throw} is a symbol that indicates the type of the
|
||||||
|
@ -679,7 +680,18 @@ procedure must be designed to accept a number of arguments that
|
||||||
corresponds to the number of arguments in all @code{throw} expressions
|
corresponds to the number of arguments in all @code{throw} expressions
|
||||||
that can be caught by this @code{catch}.
|
that can be caught by this @code{catch}.
|
||||||
|
|
||||||
@deffn {Scheme Procedure} catch key thunk handler
|
The fourth, optional argument of a @code{catch} expression is another
|
||||||
|
handler procedure, called the @dfn{pre-unwind} handler. It differs from
|
||||||
|
the third argument in that if an exception is thrown, it is called,
|
||||||
|
@emph{before} the third argument handler, in exactly the dynamic context
|
||||||
|
of the @code{throw} expression that threw the exception. This means
|
||||||
|
that it is useful for capturing or displaying the stack at the point of
|
||||||
|
the @code{throw}, or for examining other aspects of the dynamic context,
|
||||||
|
such as fluid values, before the context is unwound back to that of the
|
||||||
|
prevailing @code{catch}.
|
||||||
|
|
||||||
|
@deffn {Scheme Procedure} catch key thunk handler [pre-unwind-handler]
|
||||||
|
@deffnx {C Function} scm_catch_with_pre_unwind_handler (key, thunk, handler, pre_unwind_handler)
|
||||||
@deffnx {C Function} scm_catch (key, thunk, handler)
|
@deffnx {C Function} scm_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
|
||||||
exceptions matching @var{key}. If thunk throws to the symbol
|
exceptions matching @var{key}. If thunk throws to the symbol
|
||||||
|
@ -699,9 +711,24 @@ from further up the call chain is invoked.
|
||||||
|
|
||||||
If the key is @code{#t}, then a throw to @emph{any} symbol will
|
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}.
|
||||||
|
|
||||||
|
If a @var{pre-unwind-handler} is given and @var{thunk} throws
|
||||||
|
an exception that matches @var{key}, Guile calls the
|
||||||
|
@var{pre-unwind-handler} before unwinding the dynamic state and
|
||||||
|
invoking the main @var{handler}. @var{pre-unwind-handler} should
|
||||||
|
be a procedure with the same signature as @var{handler}, that
|
||||||
|
is @code{(lambda (key . args))}. It is typically used to save
|
||||||
|
the stack at the point where the exception occurred, but can also
|
||||||
|
query other parts of the dynamic state at that point, such as
|
||||||
|
fluid values.
|
||||||
|
|
||||||
|
A @var{pre-unwind-handler} can exit either normally or non-locally.
|
||||||
|
If it exits normally, Guile unwinds the stack and dynamic context
|
||||||
|
and then calls the normal (third argument) handler. If it exits
|
||||||
|
non-locally, that exit determines the continuation.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
If the handler procedure needs to match a variety of @code{throw}
|
If a handler procedure needs to match a variety of @code{throw}
|
||||||
expressions with varying numbers of arguments, you should write it like
|
expressions with varying numbers of arguments, you should write it like
|
||||||
this:
|
this:
|
||||||
|
|
||||||
|
@ -717,24 +744,26 @@ interpretation of the @var{args} varies from one type of exception to
|
||||||
another, but should be specified by the documentation for each exception
|
another, but should be specified by the documentation for each exception
|
||||||
type.
|
type.
|
||||||
|
|
||||||
Note that, once the handler procedure is invoked, the catch that led to
|
Note that, once the normal (post-unwind) handler procedure is invoked,
|
||||||
the handler procedure being called is no longer active. Therefore, if
|
the catch that led to the handler procedure being called is no longer
|
||||||
the handler procedure itself throws an exception, that exception can
|
active. Therefore, if the handler procedure itself throws an exception,
|
||||||
only be caught by another active catch higher up the call stack, if
|
that exception can only be caught by another active catch higher up the
|
||||||
there is one.
|
call stack, if there is one.
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
@deftypefn {C Function} SCM scm_internal_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data)
|
@deftypefn {C Function} SCM scm_c_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data, scm_t_catch_handler pre_unwind_handler, void *pre_unwind_handler_data)
|
||||||
The above @code{scm_catch} takes Scheme procedures as body and handler
|
@deftypefnx {C Function} SCM scm_internal_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data)
|
||||||
arguments. @code{scm_internal_catch} is an equivalent taking C
|
The above @code{scm_catch_with_pre_unwind_handler} and @code{scm_catch}
|
||||||
functions.
|
take Scheme procedures as body and handler arguments.
|
||||||
|
@code{scm_c_catch} and @code{scm_internal_catch} are equivalents taking
|
||||||
|
C functions.
|
||||||
|
|
||||||
@var{body} is called as @code{@var{body} (@var{body_data})} with a
|
@var{body} is called as @code{@var{body} (@var{body_data})} with a catch
|
||||||
catch on exceptions of the given @var{tag} type. If an exception is
|
on exceptions of the given @var{tag} type. If an exception is caught,
|
||||||
caught, @var{handler} is called @code{@var{handler}
|
@var{pre_unwind_handler} and @var{handler} are called as
|
||||||
(@var{handler_data}, @var{key}, @var{args})}. @var{key} and
|
@code{@var{handler} (@var{handler_data}, @var{key}, @var{args})}.
|
||||||
@var{args} are the @code{SCM} key and argument list from the
|
@var{key} and @var{args} are the @code{SCM} key and argument list from
|
||||||
@code{throw}.
|
the @code{throw}.
|
||||||
|
|
||||||
@tpindex scm_t_catch_body
|
@tpindex scm_t_catch_body
|
||||||
@tpindex scm_t_catch_handler
|
@tpindex scm_t_catch_handler
|
||||||
|
@ -761,73 +790,58 @@ Operations}).
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
|
|
||||||
@node Throw
|
@node Throw Handlers
|
||||||
@subsubsection Throwing Exceptions
|
@subsubsection Throw Handlers
|
||||||
|
|
||||||
The @code{throw} primitive is used to throw an exception. One argument,
|
It's sometimes useful to be able to intercept an exception that is being
|
||||||
the @var{key}, is mandatory, and must be a symbol; it indicates the type
|
thrown, but without changing where in the dynamic context that exception
|
||||||
of exception that is being thrown. Following the @var{key},
|
will eventually be caught. This could be to clean up some related state
|
||||||
@code{throw} accepts any number of additional arguments, whose meaning
|
or to pass information about the exception to a debugger, for example.
|
||||||
depends on the exception type. The documentation for each possible type
|
The @code{with-throw-handler} procedure provides a way to do this.
|
||||||
of exception should specify the additional arguments that are expected
|
|
||||||
for that kind of exception.
|
|
||||||
|
|
||||||
@deffn {Scheme Procedure} throw key . args
|
@deffn {Scheme Procedure} with-throw-handler key thunk handler
|
||||||
@deffnx {C Function} scm_throw (key, args)
|
@deffnx {C Function} scm_with_throw_handler (key, thunk, handler)
|
||||||
Invoke the catch form matching @var{key}, passing @var{args} to the
|
Add @var{handler} to the dynamic context as a throw handler
|
||||||
@var{handler}.
|
for key @var{key}, then invoke @var{thunk}.
|
||||||
|
|
||||||
@var{key} is a symbol. It will match catches of the same symbol or of
|
|
||||||
@code{#t}.
|
|
||||||
|
|
||||||
If there is no handler at all, Guile prints an error and then exits.
|
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
When an exception is thrown, it will be caught by the innermost
|
@deftypefn {C Function} SCM scm_c_with_throw_handler (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data, int lazy_catch_p)
|
||||||
@code{catch} expression that applies to the type of the thrown
|
The above @code{scm_with_throw_handler} takes Scheme procedures as body
|
||||||
exception; in other words, the innermost @code{catch} whose @var{key} is
|
(thunk) and handler arguments. @code{scm_c_with_throw_handler} is an
|
||||||
@code{#t} or is the same symbol as that used in the @code{throw}
|
equivalent taking C functions. See @code{scm_c_catch} (@pxref{Catch})
|
||||||
expression. Once Guile has identified the appropriate @code{catch}, it
|
for a description of the parameters, the behaviour however of course
|
||||||
handles the exception by applying that @code{catch} expression's handler
|
follows @code{with-throw-handler}.
|
||||||
procedure to the arguments of the @code{throw}.
|
@end deftypefn
|
||||||
|
|
||||||
If there is no appropriate @code{catch} for a thrown exception, Guile
|
If @var{thunk} throws an exception, Guile handles that exception by
|
||||||
prints an error to the current error port indicating an uncaught
|
invoking the innermost @code{catch} or throw handler whose key matches
|
||||||
exception, and then exits. In practice, it is quite difficult to
|
that of the exception. When the innermost thing is a throw handler,
|
||||||
observe this behaviour, because Guile when used interactively installs a
|
Guile calls the specified handler procedure using @code{(apply
|
||||||
top level @code{catch} handler that will catch all exceptions and print
|
@var{handler} key args)}. The handler procedure may either return
|
||||||
an appropriate error message @emph{without} exiting. For example, this
|
normally or exit non-locally. If it returns normally, Guile passes the
|
||||||
is what happens if you try to throw an unhandled exception in the
|
exception on to the next innermost @code{catch} or throw handler. If it
|
||||||
standard Guile REPL; note that Guile's command loop continues after the
|
exits non-locally, that exit determines the continuation.
|
||||||
error message:
|
|
||||||
|
|
||||||
@lisp
|
The behaviour of a throw handler is very similar to that of a
|
||||||
guile> (throw 'badex)
|
@code{catch} expression's optional pre-unwind handler. In particular, a
|
||||||
<unnamed port>:3:1: In procedure gsubr-apply @dots{}
|
throw handler's handler procedure is invoked in the exact dynamic
|
||||||
<unnamed port>:3:1: unhandled-exception: badex
|
context of the @code{throw} expression, just as a pre-unwind handler is.
|
||||||
ABORT: (misc-error)
|
@code{with-throw-handler} may be seen as a half-@code{catch}: it does
|
||||||
guile>
|
everything that a @code{catch} would do until the point where
|
||||||
@end lisp
|
@code{catch} would start unwinding the stack and dynamic context, but
|
||||||
|
then it rethrows to the next innermost @code{catch} or throw handler
|
||||||
The default uncaught exception behaviour can be observed by evaluating a
|
instead.
|
||||||
@code{throw} expression from the shell command line:
|
|
||||||
|
|
||||||
@example
|
|
||||||
$ guile -c "(begin (throw 'badex) (display \"here\\n\"))"
|
|
||||||
guile: uncaught throw to badex: ()
|
|
||||||
$
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
That Guile exits immediately following the uncaught exception
|
|
||||||
is shown by the absence of any output from the @code{display}
|
|
||||||
expression, because Guile never gets to the point of evaluating that
|
|
||||||
expression.
|
|
||||||
|
|
||||||
|
|
||||||
@node Lazy Catch
|
@node Lazy Catch
|
||||||
@subsubsection Catch Without Unwinding
|
@subsubsection Catch Without Unwinding
|
||||||
|
|
||||||
|
Before version 1.8, Guile's closest equivalent to
|
||||||
|
@code{with-throw-handler} was @code{lazy-catch}. From version 1.8
|
||||||
|
onwards we recommend using @code{with-throw-handler} because its
|
||||||
|
behaviour is more useful than that of @code{lazy-catch}, but
|
||||||
|
@code{lazy-catch} is still supported as well.
|
||||||
|
|
||||||
A @dfn{lazy catch} is used in the same way as a normal @code{catch},
|
A @dfn{lazy catch} is used in the same way as a normal @code{catch},
|
||||||
with @var{key}, @var{thunk} and @var{handler} arguments specifying the
|
with @var{key}, @var{thunk} and @var{handler} arguments specifying the
|
||||||
exception type, normal case code and handler procedure, but differs in
|
exception type, normal case code and handler procedure, but differs in
|
||||||
|
@ -839,8 +853,10 @@ that caused the handler to be invoked.
|
||||||
@deffnx {C Function} scm_lazy_catch (key, thunk, handler)
|
@deffnx {C Function} scm_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 before invoking @var{handler}.
|
not unwind the stack before invoking @var{handler}.
|
||||||
The @var{handler} procedure is not allowed to return:
|
If the @var{handler} procedure returns normally, Guile
|
||||||
it must throw to another catch, or otherwise exit non-locally.
|
rethrows the same exception again to the next innermost catch,
|
||||||
|
lazy-catch or throw handler. If the @var{handler} exits
|
||||||
|
non-locally, that exit determines the continuation.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deftypefn {C Function} SCM scm_internal_lazy_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data)
|
@deftypefn {C Function} SCM scm_internal_lazy_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data)
|
||||||
|
@ -851,11 +867,9 @@ a description of the parameters, the behaviour however of course
|
||||||
follows @code{lazy-catch}.
|
follows @code{lazy-catch}.
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
Typically, @var{handler} should save any desired state associated with
|
Typically @var{handler} is used to display a backtrace of the stack at
|
||||||
the stack at the point where the corresponding @code{throw} occurred,
|
the point where the corresponding @code{throw} occurred, or to save off
|
||||||
and then throw an exception itself --- usually the same exception as the
|
this information for possible display later.
|
||||||
one it caught. If @var{handler} is invoked and does @emph{not} throw an
|
|
||||||
exception, Guile itself throws an exception with key @code{misc-error}.
|
|
||||||
|
|
||||||
Not unwinding the stack means that throwing an exception that is caught
|
Not unwinding the stack means that throwing an exception that is caught
|
||||||
by a @code{lazy-catch} is @emph{almost} equivalent to calling the
|
by a @code{lazy-catch} is @emph{almost} equivalent to calling the
|
||||||
|
@ -926,6 +940,123 @@ debuggers and other reflective programming tools that need to access the
|
||||||
state of the call stack at the exact point where an exception or an
|
state of the call stack at the exact point where an exception or an
|
||||||
error is thrown. For an example of this, see REFFIXME:stack-catch.
|
error is thrown. For an example of this, see REFFIXME:stack-catch.
|
||||||
|
|
||||||
|
It should be obvious from the above that @code{lazy-catch} is very
|
||||||
|
similar to @code{with-throw-handler}. In fact Guile implements
|
||||||
|
@code{lazy-catch} in exactly the same way as @code{with-throw-handler},
|
||||||
|
except with a flag set to say ``where there are slight differences
|
||||||
|
between what @code{with-throw-handler} and @code{lazy-catch} would do,
|
||||||
|
do what @code{lazy-catch} has always done''. There are two such
|
||||||
|
differences:
|
||||||
|
|
||||||
|
@enumerate
|
||||||
|
@item
|
||||||
|
@code{with-throw-handler} handlers execute in the full dynamic context
|
||||||
|
of the originating @code{throw} call. @code{lazy-catch} handlers
|
||||||
|
execute in the dynamic context of the @code{lazy-catch} expression,
|
||||||
|
excepting only that the stack has not yet been unwound from the point of
|
||||||
|
the @code{throw} call.
|
||||||
|
|
||||||
|
@item
|
||||||
|
If a @code{with-throw-handler} handler throws to a key that does not
|
||||||
|
match the @code{with-throw-handler} expression's @var{key}, the new
|
||||||
|
throw may be handled by a @code{catch} or throw handler that is _closer_
|
||||||
|
to the throw than the first @code{with-throw-handler}. If a
|
||||||
|
@code{lazy-catch} handler throws, it will always be handled by a
|
||||||
|
@code{catch} or throw handler that is higher up the dynamic context than
|
||||||
|
the first @code{lazy-catch}.
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
|
Here is an example to illustrate the second difference:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
(catch 'a
|
||||||
|
(lambda ()
|
||||||
|
(with-throw-handler 'b
|
||||||
|
(lambda ()
|
||||||
|
(catch 'a
|
||||||
|
(lambda ()
|
||||||
|
(throw 'b))
|
||||||
|
inner-handler))
|
||||||
|
(lambda (key . args)
|
||||||
|
(throw 'a))))
|
||||||
|
outer-handler)
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
This code will call @code{inner-handler} and then continue with the
|
||||||
|
continuation of the inner @code{catch}. If the
|
||||||
|
@code{with-throw-handler} was changed to @code{lazy-catch}, however, the
|
||||||
|
code would call @code{outer-handler} and then continue with the
|
||||||
|
continuation of the outer @code{catch}.
|
||||||
|
|
||||||
|
Modulo these two differences, any statements in the previous and
|
||||||
|
following subsections about throw handlers apply to lazy catches as
|
||||||
|
well.
|
||||||
|
|
||||||
|
|
||||||
|
@node Throw
|
||||||
|
@subsubsection Throwing Exceptions
|
||||||
|
|
||||||
|
The @code{throw} primitive is used to throw an exception. One argument,
|
||||||
|
the @var{key}, is mandatory, and must be a symbol; it indicates the type
|
||||||
|
of exception that is being thrown. Following the @var{key},
|
||||||
|
@code{throw} accepts any number of additional arguments, whose meaning
|
||||||
|
depends on the exception type. The documentation for each possible type
|
||||||
|
of exception should specify the additional arguments that are expected
|
||||||
|
for that kind of exception.
|
||||||
|
|
||||||
|
@deffn {Scheme Procedure} throw key . args
|
||||||
|
@deffnx {C Function} scm_throw (key, args)
|
||||||
|
Invoke the catch form matching @var{key}, passing @var{args} to the
|
||||||
|
@var{handler}.
|
||||||
|
|
||||||
|
@var{key} is a symbol. It will match catches of the same symbol or of
|
||||||
|
@code{#t}.
|
||||||
|
|
||||||
|
If there is no handler at all, Guile prints an error and then exits.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
When an exception is thrown, it will be caught by the innermost
|
||||||
|
@code{catch} or throw handler that applies to the type of the thrown
|
||||||
|
exception; in other words, whose @var{key} is either @code{#t} or the
|
||||||
|
same symbol as that used in the @code{throw} expression. Once Guile has
|
||||||
|
identified the appropriate @code{catch} or throw handler, it handles the
|
||||||
|
exception by applying the relevant handler procedure(s) to the arguments
|
||||||
|
of the @code{throw}.
|
||||||
|
|
||||||
|
If there is no appropriate @code{catch} or throw handler for a thrown
|
||||||
|
exception, Guile prints an error to the current error port indicating an
|
||||||
|
uncaught exception, and then exits. In practice, it is quite difficult
|
||||||
|
to observe this behaviour, because Guile when used interactively
|
||||||
|
installs a top level @code{catch} handler that will catch all exceptions
|
||||||
|
and print an appropriate error message @emph{without} exiting. For
|
||||||
|
example, this is what happens if you try to throw an unhandled exception
|
||||||
|
in the standard Guile REPL; note that Guile's command loop continues
|
||||||
|
after the error message:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
guile> (throw 'badex)
|
||||||
|
<unnamed port>:3:1: In procedure gsubr-apply @dots{}
|
||||||
|
<unnamed port>:3:1: unhandled-exception: badex
|
||||||
|
ABORT: (misc-error)
|
||||||
|
guile>
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
The default uncaught exception behaviour can be observed by evaluating a
|
||||||
|
@code{throw} expression from the shell command line:
|
||||||
|
|
||||||
|
@example
|
||||||
|
$ guile -c "(begin (throw 'badex) (display \"here\\n\"))"
|
||||||
|
guile: uncaught throw to badex: ()
|
||||||
|
$
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
That Guile exits immediately following the uncaught exception
|
||||||
|
is shown by the absence of any output from the @code{display}
|
||||||
|
expression, because Guile never gets to the point of evaluating that
|
||||||
|
expression.
|
||||||
|
|
||||||
|
|
||||||
@node Exception Implementation
|
@node Exception Implementation
|
||||||
@subsubsection How Guile Implements Exceptions
|
@subsubsection How Guile Implements Exceptions
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue