@c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual.
-@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004
+@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, 2011, 2012
@c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions.
-@page
@node Control Mechanisms
@section Controlling the Flow of Program Execution
flow of Scheme affects C code.
@menu
-* begin:: Evaluating a sequence of expressions.
-* if cond case:: Simple conditional evaluation.
+* begin:: Sequencing and splicing.
+* Conditionals:: If, when, unless, case, and cond.
* and or:: Conditional evaluation of a sequence.
* while do:: Iteration mechanisms.
-* Continuations:: Continuations.
+* Prompts:: Composable, delimited continuations.
+* Continuations:: Non-composable continuations.
* Multiple Values:: Returning and accepting multiple values.
* Exceptions:: Throwing and catching exceptions.
* Error Reporting:: Procedures for signaling errors.
* Dynamic Wind:: Dealing with non-local entrance/exit.
* Handling Errors:: How to handle errors in C code.
+* Continuation Barriers:: Protection from non-local control flow.
@end menu
@node begin
-@subsection Evaluating a Sequence of Expressions
+@subsection Sequencing and Splicing
@cindex begin
@cindex sequencing
@cindex expression sequencing
-The @code{begin} syntax is used for grouping several expressions
-together so that they are treated as if they were one expression.
-This is particularly important when syntactic expressions are used
-which only allow one expression, but the programmer wants to use more
-than one expression in that place. As an example, consider the
-conditional expression below:
+As an expression, the @code{begin} syntax is used to evaluate a sequence
+of sub-expressions in order. Consider the conditional expression below:
@lisp
(if (> x 0)
(begin (display "greater") (newline)))
@end lisp
-If the two calls to @code{display} and @code{newline} were not embedded
-in a @code{begin}-statement, the call to @code{newline} would get
-misinterpreted as the else-branch of the @code{if}-expression.
+If the test is true, we want to display ``greater'' to the current
+output port, then display a newline. We use @code{begin} to form a
+compound expression out of this sequence of sub-expressions.
-@deffn syntax begin expr1 expr2 @dots{}
-The expression(s) are evaluated in left-to-right order and the value
-of the last expression is returned as the value of the
+@deffn syntax begin expr @dots{}
+The expression(s) are evaluated in left-to-right order and the value of
+the last expression is returned as the value of the
@code{begin}-expression. This expression type is used when the
expressions before the last one are evaluated for their side effects.
-
-Guile also allows the expression @code{(begin)}, a @code{begin} with no
-sub-expressions. Such an expression returns the `unspecified' value.
@end deffn
-@node if cond case
+@cindex splicing
+@cindex definition splicing
+
+The @code{begin} syntax has another role in definition context
+(@pxref{Internal Definitions}). A @code{begin} form in a definition
+context @dfn{splices} its subforms into its place. For example,
+consider the following procedure:
+
+@lisp
+(define (make-seal)
+ (define-sealant seal open)
+ (values seal open))
+@end lisp
+
+Let us assume the existence of a @code{define-sealant} macro that
+expands out to some definitions wrapped in a @code{begin}, like so:
+
+@lisp
+(define (make-seal)
+ (begin
+ (define seal-tag
+ (list 'seal))
+ (define (seal x)
+ (cons seal-tag x))
+ (define (sealed? x)
+ (and (pair? x) (eq? (car x) seal-tag)))
+ (define (open x)
+ (if (sealed? x)
+ (cdr x)
+ (error "Expected a sealed value:" x))))
+ (values seal open))
+@end lisp
+
+Here, because the @code{begin} is in definition context, its subforms
+are @dfn{spliced} into the place of the @code{begin}. This allows the
+definitions created by the macro to be visible to the following
+expression, the @code{values} form.
+
+It is a fine point, but splicing and sequencing are different. It can
+make sense to splice zero forms, because it can make sense to have zero
+internal definitions before the expressions in a procedure or lexical
+binding form. However it does not make sense to have a sequence of zero
+expressions, because in that case it would not be clear what the value
+of the sequence would be, because in a sequence of zero expressions,
+there can be no last value. Sequencing zero expressions is an error.
+
+It would be more elegant in some ways to eliminate splicing from the
+Scheme language, and without macros (@pxref{Macros}), that would be a
+good idea. But it is useful to be able to write macros that expand out
+to multiple definitions, as in @code{define-sealant} above, so Scheme
+abuses the @code{begin} form for these two tasks.
+
+@node Conditionals
@subsection Simple Conditional Evaluation
@cindex conditional evaluation
@cindex if
+@cindex when
+@cindex unless
@cindex case
@cindex cond
All arguments may be arbitrary expressions. First, @var{test} is
evaluated. If it returns a true value, the expression @var{consequent}
is evaluated and @var{alternate} is ignored. If @var{test} evaluates to
-@code{#f}, @var{alternate} is evaluated instead. The value of the
-evaluated branch (@var{consequent} or @var{alternate}) is returned as
-the value of the @code{if} expression.
+@code{#f}, @var{alternate} is evaluated instead. The values of the
+evaluated branch (@var{consequent} or @var{alternate}) are returned as
+the values of the @code{if} expression.
When @var{alternate} is omitted and the @var{test} evaluates to
@code{#f}, the value of the expression is not specified.
@end deffn
+When you go to write an @code{if} without an alternate (a @dfn{one-armed
+@code{if}}), part of what you are expressing is that you don't care
+about the return value (or values) of the expression. As such, you are
+more interested in the @emph{effect} of evaluating the consequent
+expression. (By convention, we use the word @dfn{statement} to refer to
+an expression that is evaluated for effect, not for value).
+
+In such a case, it is considered more clear to express these intentions
+with these special forms, @code{when} and @code{unless}. As an added
+bonus, these forms accept multiple statements to evaluate, which are
+implicitly wrapped in a @code{begin}.
+
+@deffn {Scheme Syntax} when test statement1 statement2 ...
+@deffnx {Scheme Syntax} unless test statement1 statement2 ...
+The actual definitions of these forms are in many ways their most clear
+documentation:
+
+@example
+(define-syntax-rule (when test stmt stmt* ...)
+ (if test (begin stmt stmt* ...)))
+
+(define-syntax-rule (unless condition stmt stmt* ...)
+ (if (not test) (begin stmt stmt* ...)))
+@end example
+
+That is to say, @code{when} evaluates its consequent statements in order
+if @var{test} is true. @code{unless} is the opposite: it evaluates the
+statements if @var{test} is false.
+@end deffn
+
@deffn syntax cond clause1 clause2 @dots{}
Each @code{cond}-clause must look like this:
@end deffn
@deffn syntax case key clause1 clause2 @dots{}
-@var{key} may be any expression, the @var{clause}s must have the form
+@var{key} may be any expression, and the @var{clause}s must have the form
@lisp
((@var{datum1} @dots{}) @var{expr1} @var{expr2} @dots{})
@end lisp
+or
+
+@lisp
+((@var{datum1} @dots{}) => @var{expression})
+@end lisp
+
and the last @var{clause} may have the form
@lisp
(else @var{expr1} @var{expr2} @dots{})
@end lisp
+or
+
+@lisp
+(else => @var{expression})
+@end lisp
+
All @var{datum}s must be distinct. First, @var{key} is evaluated. The
-the result of this evaluation is compared against all @var{datum}s using
+result of this evaluation is compared against all @var{datum} values using
@code{eqv?}. When this comparison succeeds, the expression(s) following
the @var{datum} are evaluated from left to right, returning the value of
the last expression as the result of the @code{case} expression.
@code{else}-clause, the expressions following the @code{else} are
evaluated. If there is no such clause, the result of the expression is
unspecified.
+
+For the @code{=>} clause types, @var{expression} is evaluated and the
+resulting procedure is applied to the value of @var{key}. The result of
+this procedure application is then the result of the
+@code{case}-expression.
@end deffn
R5RS defines a construct for programming loops, calling @code{do}. In
addition, Guile has an explicit looping syntax called @code{while}.
-@deffn syntax do ((variable init [step]) @dots{}) (test [expr @dots{}]) body @dots{}
+@deffn syntax do ((variable init [step]) @dots{}) (test expr @dots{}) body @dots{}
Bind @var{variable}s and evaluate @var{body} until @var{test} is true.
The return value is the last @var{expr} after @var{test}, if given. A
simple example will illustrate the basic form,
@deffn syntax while cond body @dots{}
Run a loop executing the @var{body} forms while @var{cond} is true.
@var{cond} is tested at the start of each iteration, so if it's
-@code{#f} the first time then @var{body} is not executed at all. The
-return value is unspecified.
+@code{#f} the first time then @var{body} is not executed at all.
Within @code{while}, two extra bindings are provided, they can be used
from both @var{cond} and @var{body}.
-@deffn {Scheme Procedure} break
+@deffn {Scheme Procedure} break break-arg @dots{}
Break out of the @code{while} form.
@end deffn
@var{cond} again, etc.
@end deffn
+If the loop terminates normally, by the @var{cond} evaluating to
+@code{#f}, then the @code{while} expression as a whole evaluates to
+@code{#f}. If it terminates by a call to @code{break} with some number
+of arguments, those arguments are returned from the @code{while}
+expression, as multiple values. Otherwise if it terminates by a call to
+@code{break} with no arguments, then return value is @code{#t}.
+
+@example
+(while #f (error "not reached")) @result{} #f
+(while #t (break)) @result{} #t
+(while #t (break 1 2 3)) @result{} 1 2 3
+@end example
+
Each @code{while} form gets its own @code{break} and @code{continue}
procedures, operating on that @code{while}. This means when loops are
nested the outer @code{break} can be used to escape all the way out.
@end deffn
+@node Prompts
+@subsection Prompts
+@cindex prompts
+@cindex delimited continuations
+@cindex composable continuations
+@cindex non-local exit
+
+Prompts are control-flow barriers between different parts of a program. In the
+same way that a user sees a shell prompt (e.g., the Bash prompt) as a barrier
+between the operating system and her programs, Scheme prompts allow the Scheme
+programmer to treat parts of programs as if they were running in different
+operating systems.
+
+We use this roundabout explanation because, unless you're a functional
+programming junkie, you probably haven't heard the term, ``delimited, composable
+continuation''. That's OK; it's a relatively recent topic, but a very useful
+one to know about.
+
+@menu
+* Prompt Primitives:: Call-with-prompt and abort-to-prompt.
+* Shift and Reset:: The zoo of delimited control operators.
+@end menu
+
+@node Prompt Primitives
+@subsubsection Prompt Primitives
+
+Guile's primitive delimited control operators are
+@code{call-with-prompt} and @code{abort-to-prompt}.
+
+@deffn {Scheme Procedure} call-with-prompt tag thunk handler
+Set up a prompt, and call @var{thunk} within that prompt.
+
+During the dynamic extent of the call to @var{thunk}, a prompt named @var{tag}
+will be present in the dynamic context, such that if a user calls
+@code{abort-to-prompt} (see below) with that tag, control rewinds back to the
+prompt, and the @var{handler} is run.
+
+@var{handler} must be a procedure. The first argument to @var{handler} will be
+the state of the computation begun when @var{thunk} was called, and ending with
+the call to @code{abort-to-prompt}. The remaining arguments to @var{handler} are
+those passed to @code{abort-to-prompt}.
+@end deffn
+
+@deffn {Scheme Procedure} make-prompt-tag [stem]
+Make a new prompt tag. A prompt tag is simply a unique object.
+Currently, a prompt tag is a fresh pair. This may change in some future
+Guile version.
+@end deffn
+
+@deffn {Scheme Procedure} default-prompt-tag
+Return the default prompt tag. Having a distinguished default prompt
+tag allows some useful prompt and abort idioms, discussed in the next
+section. Note that @code{default-prompt-tag} is actually a parameter,
+and so may be dynamically rebound using @code{parameterize}.
+@xref{Parameters}.
+@end deffn
+
+@deffn {Scheme Procedure} abort-to-prompt tag val1 val2 @dots{}
+Unwind the dynamic and control context to the nearest prompt named @var{tag},
+also passing the given values.
+@end deffn
+
+C programmers may recognize @code{call-with-prompt} and @code{abort-to-prompt}
+as a fancy kind of @code{setjmp} and @code{longjmp}, respectively. Prompts are
+indeed quite useful as non-local escape mechanisms. Guile's @code{catch} and
+@code{throw} are implemented in terms of prompts. Prompts are more convenient
+than @code{longjmp}, in that one has the opportunity to pass multiple values to
+the jump target.
+
+Also unlike @code{longjmp}, the prompt handler is given the full state of the
+process that was aborted, as the first argument to the prompt's handler. That
+state is the @dfn{continuation} of the computation wrapped by the prompt. It is
+a @dfn{delimited continuation}, because it is not the whole continuation of the
+program; rather, just the computation initiated by the call to
+@code{call-with-prompt}.
+
+The continuation is a procedure, and may be reinstated simply by invoking it,
+with any number of values. Here's where things get interesting, and complicated
+as well. Besides being described as delimited, continuations reified by prompts
+are also @dfn{composable}, because invoking a prompt-saved continuation composes
+that continuation with the current one.
+
+Imagine you have saved a continuation via call-with-prompt:
+
+@example
+(define cont
+ (call-with-prompt
+ ;; tag
+ 'foo
+ ;; thunk
+ (lambda ()
+ (+ 34 (abort-to-prompt 'foo)))
+ ;; handler
+ (lambda (k) k)))
+@end example
+
+The resulting continuation is the addition of 34. It's as if you had written:
+
+@example
+(define cont
+ (lambda (x)
+ (+ 34 x)))
+@end example
+
+So, if we call @code{cont} with one numeric value, we get that number,
+incremented by 34:
+
+@example
+(cont 8)
+@result{} 42
+(* 2 (cont 8))
+@result{} 84
+@end example
+
+The last example illustrates what we mean when we say, "composes with the
+current continuation". We mean that there is a current continuation -- some
+remaining things to compute, like @code{(lambda (x) (* x 2))} -- and that
+calling the saved continuation doesn't wipe out the current continuation, it
+composes the saved continuation with the current one.
+
+We're belaboring the point here because traditional Scheme continuations, as
+discussed in the next section, aren't composable, and are actually less
+expressive than continuations captured by prompts. But there's a place for them
+both.
+
+Before moving on, we should mention that if the handler of a prompt is a
+@code{lambda} expression, and the first argument isn't referenced, an abort to
+that prompt will not cause a continuation to be reified. This can be an
+important efficiency consideration to keep in mind.
+
+@node Shift and Reset
+@subsubsection Shift, Reset, and All That
+
+There is a whole zoo of delimited control operators, and as it does not
+seem to be a bounded set, Guile implements support for them in a
+separate module:
+
+@example
+(use-modules (ice-9 control))
+@end example
+
+Firstly, we have a helpful abbreviation for the @code{call-with-prompt}
+operator.
+
+@deffn {Scheme Syntax} % expr
+@deffnx {Scheme Syntax} % expr handler
+@deffnx {Scheme Syntax} % tag expr handler
+Evaluate @var{expr} in a prompt, optionally specifying a tag and a
+handler. If no tag is given, the default prompt tag is used.
+
+If no handler is given, a default handler is installed. The default
+handler accepts a procedure of one argument, which will called on the
+captured continuation, within a prompt.
+
+Sometimes it's easier just to show code, as in this case:
+
+@example
+(define (default-prompt-handler k proc)
+ (% (default-prompt-tag)
+ (proc k)
+ default-prompt-handler))
+@end example
+
+The @code{%} symbol is chosen because it looks like a prompt.
+@end deffn
+
+Likewise there is an abbreviation for @code{abort-to-prompt}, which
+assumes the default prompt tag:
+
+@deffn {Scheme Procedure} abort val1 val2 @dots{}
+Abort to the default prompt tag, passing @var{val1} @var{val2} @dots{}
+to the handler.
+@end deffn
+
+As mentioned before, @code{(ice-9 control)} also provides other
+delimited control operators. This section is a bit technical, and
+first-time users of delimited continuations should probably come back to
+it after some practice with @code{%}.
+
+Still here? So, when one implements a delimited control operator like
+@code{call-with-prompt}, one needs to make two decisions. Firstly, does
+the handler run within or outside the prompt? Having the handler run
+within the prompt allows an abort inside the handler to return to the
+same prompt handler, which is often useful. However it prevents tail
+calls from the handler, so it is less general.
+
+Similarly, does invoking a captured continuation reinstate a prompt?
+Again we have the tradeoff of convenience versus proper tail calls.
+
+These decisions are captured in the Felleisen @dfn{F} operator. If
+neither the continuations nor the handlers implicitly add a prompt, the
+operator is known as @dfn{--F--}. This is the case for Guile's
+@code{call-with-prompt} and @code{abort-to-prompt}.
+
+If both continuation and handler implicitly add prompts, then the
+operator is @dfn{+F+}. @code{shift} and @code{reset} are such
+operators.
+
+@deffn {Scheme Syntax} reset body1 body2 @dots{}
+Establish a prompt, and evaluate @var{body1} @var{body2} @dots{} within
+that prompt.
+
+The prompt handler is designed to work with @code{shift}, described
+below.
+@end deffn
+
+@deffn {Scheme Syntax} shift cont body1 body2 @dots{}
+Abort to the nearest @code{reset}, and evaluate @var{body1} @var{body2}
+@dots{} in a context in which the captured continuation is bound to
+@var{cont}.
+
+As mentioned above, taken together, the @var{body1} @var{body2} @dots{}
+expressions and the invocations of @var{cont} implicitly establish a
+prompt.
+@end deffn
+
+Interested readers are invited to explore Oleg Kiselyov's wonderful web
+site at @uref{http://okmij.org/ftp/}, for more information on these
+operators.
+
+
@node Continuations
@subsection Continuations
@cindex continuations
This is in common use since the latter is rather long.
@end deffn
-@deftypefn {C Function} SCM scm_make_continuation (int *first)
-Capture the current continuation as described above. The return value
-is the new continuation, and @var{*first} is set to 1.
-
-When the continuation is invoked, @code{scm_make_continuation} will
-return again, this time returning the value (or set of multiple
-values) passed in that invocation, and with @var{*first} set to 0.
-@end deftypefn
-
@sp 1
@noindent
Here is a simple example,
about continuations. Basically continuations are captured by a block
copy of the stack, and resumed by copying back.
-For this reason, generally continuations should be used only when
-there is no other simple way to achieve the desired result, or when
-the elegance of the continuation mechanism outweighs the need for
-performance.
+For this reason, continuations captured by @code{call/cc} should be used only
+when there is no other simple way to achieve the desired result, or when the
+elegance of the continuation mechanism outweighs the need for performance.
Escapes upwards from loops or nested functions are generally best
-handled with exceptions (@pxref{Exceptions}). Coroutines can be
+handled with prompts (@pxref{Prompts}). Coroutines can be
efficiently implemented with cooperating threads (a thread holds a
full program stack but doesn't copy it around the way continuations
do).
parameters.
@rnindex values
-@deffn {Scheme Procedure} values arg1 @dots{} argN
+@deffn {Scheme Procedure} values arg @dots{}
@deffnx {C Function} scm_values (args)
Delivers all of its arguments to its continuation. Except for
continuations created by the @code{call-with-values} procedure,
@var{args}, so @var{args} should not be modified subsequently.
@end deffn
+@deftypefn {C Function} SCM scm_c_values (SCM *base, size_t n)
+@code{scm_c_values} is an alternative to @code{scm_values}. It creates
+a new values object, and copies into it the @var{n} values starting from
+@var{base}.
+
+Currently this creates a list and passes it to @code{scm_values}, but we
+expect that in the future we will be able to use more a efficient
+representation.
+@end deftypefn
+
+@deftypefn {C Function} size_t scm_c_nvalues (SCM obj)
+If @var{obj} is a multiple-values object, returns the number of values
+it contains. Otherwise returns 1.
+@end deftypefn
+
+@deftypefn {C Function} SCM scm_c_value_ref (SCM obj, size_t idx)
+Returns the value at the position specified by @var{idx} in
+@var{obj}. Note that @var{obj} will ordinarily be a
+multiple-values object, but it need not be. Any other object
+represents a single value (itself), and is handled appropriately.
+@end deftypefn
+
@rnindex call-with-values
@deffn {Scheme Procedure} call-with-values producer consumer
Calls its @var{producer} argument with no values and a
@menu
* Exception Terminology:: Different ways to say the same thing.
* Catch:: Setting up to catch exceptions.
-* Throw Handlers:: Adding extra handling to a throw.
-* Lazy Catch:: Catch without unwinding the stack.
+* Throw Handlers:: Handling exceptions before unwinding the stack.
* Throw:: Throwing an exception.
* Exception Implementation:: How Guile implements exceptions.
@end menu
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
+(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
@subsubsection Throw Handlers
It's sometimes useful to be able to intercept an exception that is being
-thrown, but without changing where in the dynamic context that exception
-will eventually be caught. This could be to clean up some related state
-or to pass information about the exception to a debugger, for example.
-The @code{with-throw-handler} procedure provides a way to do this.
+thrown before the stack is unwound. This could be to clean up some
+related state, to print a backtrace, or to pass information about the
+exception to a debugger, for example. The @code{with-throw-handler}
+procedure provides a way to do this.
@deffn {Scheme Procedure} with-throw-handler key thunk handler
@deffnx {C Function} scm_with_throw_handler (key, thunk, handler)
Add @var{handler} to the dynamic context as a throw handler
for key @var{key}, then invoke @var{thunk}.
+
+This behaves exactly like @code{catch}, except that it does not unwind
+the stack before invoking @var{handler}. If the @var{handler} procedure
+returns normally, Guile rethrows the same exception again to the next
+innermost catch or throw handler. @var{handler} may exit nonlocally, of
+course, via an explicit throw or via invoking a continuation.
@end deffn
+Typically @var{handler} is used to display a backtrace of the stack at
+the point where the corresponding @code{throw} occurred, or to save off
+this information for possible display later.
+
+Not unwinding the stack means that throwing an exception that is handled
+via a throw handler is equivalent to calling the throw handler handler
+inline instead of each @code{throw}, and then omitting the surrounding
+@code{with-throw-handler}. In other words,
+
+@lisp
+(with-throw-handler 'key
+ (lambda () @dots{} (throw 'key args @dots{}) @dots{})
+ handler)
+@end lisp
+
+@noindent
+is mostly equivalent to
+
+@lisp
+((lambda () @dots{} (handler 'key args @dots{}) @dots{}))
+@end lisp
+
+In particular, the dynamic context when @var{handler} is invoked is that
+of the site where @code{throw} is called. The examples are not quite
+equivalent, because the body of a @code{with-throw-handler} is not in
+tail position with respect to the @code{with-throw-handler}, and if
+@var{handler} exits normally, Guile arranges to rethrow the error, but
+hopefully the intention is clear. (For an introduction to what is meant
+by dynamic context, @xref{Dynamic Wind}.)
+
@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)
The above @code{scm_with_throw_handler} takes Scheme procedures as body
(thunk) and handler arguments. @code{scm_c_with_throw_handler} is an
then it rethrows to the next innermost @code{catch} or throw handler
instead.
+Note also that since the dynamic context is not unwound, 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 @emph{closer} to
+the throw than the first @code{with-throw-handler}.
-@node Lazy Catch
-@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},
-with @var{key}, @var{thunk} and @var{handler} arguments specifying the
-exception type, normal case code and handler procedure, but differs in
-one important respect: the handler procedure is executed without
-unwinding the call stack from the context of the @code{throw} expression
-that caused the handler to be invoked.
-
-@deffn {Scheme Procedure} lazy-catch key thunk handler
-@deffnx {C Function} scm_lazy_catch (key, thunk, handler)
-This behaves exactly like @code{catch}, except that it does
-not unwind the stack before invoking @var{handler}.
-If the @var{handler} procedure returns normally, Guile
-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
-
-@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)
-The above @code{scm_lazy_catch} takes Scheme procedures as body and
-handler arguments. @code{scm_internal_lazy_catch} is an equivalent
-taking C functions. See @code{scm_internal_catch} (@pxref{Catch}) for
-a description of the parameters, the behaviour however of course
-follows @code{lazy-catch}.
-@end deftypefn
-
-Typically @var{handler} is used to display a backtrace of the stack at
-the point where the corresponding @code{throw} occurred, or to save off
-this information for possible display later.
-
-Not unwinding the stack means that throwing an exception that is caught
-by a @code{lazy-catch} is @emph{almost} equivalent to calling the
-@code{lazy-catch}'s handler inline instead of each @code{throw}, and
-then omitting the surrounding @code{lazy-catch}. In other words,
-
-@lisp
-(lazy-catch 'key
- (lambda () @dots{} (throw 'key args @dots{}) @dots{})
- handler)
-@end lisp
-
-@noindent
-is @emph{almost} equivalent to
-
-@lisp
-((lambda () @dots{} (handler 'key args @dots{}) @dots{}))
-@end lisp
-
-@noindent
-But why only @emph{almost}? The difference is that with
-@code{lazy-catch} (as with normal @code{catch}), the dynamic context is
-unwound back to just outside the @code{lazy-catch} expression before
-invoking the handler. (For an introduction to what is meant by dynamic
-context, @xref{Dynamic Wind}.)
-
-Then, when the handler @emph{itself} throws an exception, that exception
-must be caught by some kind of @code{catch} (including perhaps another
-@code{lazy-catch}) higher up the call stack.
-
-The dynamic context also includes @code{with-fluids} blocks
-(@pxref{Fluids and Dynamic States}),
-so the effect of unwinding the dynamic context can also be seen in fluid
-variable values. This is illustrated by the following code, in which
-the normal case thunk uses @code{with-fluids} to temporarily change the
-value of a fluid:
-
-@lisp
-(define f (make-fluid))
-(fluid-set! f "top level value")
-
-(define (handler . args)
- (cons (fluid-ref f) args))
-
-(lazy-catch 'foo
- (lambda ()
- (with-fluids ((f "local value"))
- (throw 'foo)))
- handler)
-@result{}
-("top level value" foo)
-
-((lambda ()
- (with-fluids ((f "local value"))
- (handler 'foo))))
-@result{}
-("local value" foo)
-@end lisp
-
-@noindent
-In the @code{lazy-catch} version, the unwinding of dynamic context
-restores @code{f} to its value outside the @code{with-fluids} block
-before the handler is invoked, so the handler's @code{(fluid-ref f)}
-returns the external value.
-
-@code{lazy-catch} is useful because it permits the implementation of
-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
-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:
+Here is an example to illustrate this behavior:
@lisp
(catch 'a
@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.
+continuation of the inner @code{catch}.
@node Throw
of exception should specify the additional arguments that are expected
for that kind of exception.
-@deffn {Scheme Procedure} throw key . args
+@deffn {Scheme Procedure} throw key arg @dots{}
@deffnx {C Function} scm_throw (key, args)
-Invoke the catch form matching @var{key}, passing @var{args} to the
-@var{handler}.
+Invoke the catch form matching @var{key}, passing @var{arg} @dots{} to
+the @var{handler}.
@var{key} is a symbol. It will match catches of the same symbol or of
@code{#t}.
conditions that are implemented on top of the exception primitives just
described.
-@deffn {Scheme Procedure} error msg args @dots{}
+@deffn {Scheme Procedure} error msg arg @dots{}
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{arg} @enddots{}.
@end deffn
@deffn {Scheme Procedure} scm-error key subr message args data
@table @code
@item SCM_F_DYNWIND_REWINDABLE
The dynamic context is @dfn{rewindable}. This means that it can be
-reentered non-locally (via the invokation of a continuation). The
+reentered non-locally (via the invocation of a continuation). The
default is that a dynwind context can not be reentered non-locally.
@end table
back on reentry. Thus reentry can not be allowed.
The consequence is that continuations become less useful when
-non-reenterable contexts are captured, but you don't need to worry
+non-reentrant contexts are captured, but you don't need to worry
about that too much.
The context is ended either implicitly when a non-local exit happens,
In addition to @code{catch} and @code{throw}, the following Scheme
facilities are available:
-@deffn {Scheme Procedure} display-error stack port subr message args rest
-@deffnx {C Function} scm_display_error (stack, port, subr, message, args, rest)
+@deffn {Scheme Procedure} display-error frame port subr message args rest
+@deffnx {C Function} scm_display_error (frame, port, subr, message, args, rest)
Display an error message to the output port @var{port}.
-@var{stack} is the saved stack for the error, @var{subr} is
+@var{frame} is the frame in which the error occurred, @var{subr} is
the name of the procedure in which the error occurred and
@var{message} is the actual error message, which may contain
formatting instructions. These will format the arguments in
@deftypefnx {C Function} void scm_out_of_range (char *@var{subr}, SCM @var{bad_value})
@deftypefnx {C Function} void scm_wrong_num_args (SCM @var{proc})
@deftypefnx {C Function} void scm_wrong_type_arg (char *@var{subr}, int @var{argnum}, SCM @var{bad_value})
+@deftypefnx {C Function} void scm_wrong_type_arg_msg (char *@var{subr}, int @var{argnum}, SCM @var{bad_value}, const char *@var{expected})
@deftypefnx {C Function} void scm_memory_error (char *@var{subr})
Throw an error with the various keys described above.
+@deftypefnx {C Function} void scm_misc_error (const char *@var{subr}, const char *@var{message}, SCM @var{args})
+
+In @code{scm_wrong_num_args}, @var{proc} should be a Scheme symbol
+which is the name of the procedure incorrectly invoked. The other
+routines take the name of the invoked procedure as a C string.
+
+In @code{scm_wrong_type_arg_msg}, @var{expected} is a C string
+describing the type of argument that was expected.
+
+In @code{scm_misc_error}, @var{message} is the error message string,
+possibly containing @code{simple-format} escapes (@pxref{Writing}), and
+the corresponding arguments in the @var{args} list.
+@end deftypefn
+
+
+@subsubsection Signalling Type Errors
+
+Every function visible at the Scheme level should aggressively check the
+types of its arguments, to avoid misinterpreting a value, and perhaps
+causing a segmentation fault. Guile provides some macros to make this
+easier.
+
+@deftypefn Macro void SCM_ASSERT (int @var{test}, SCM @var{obj}, unsigned int @var{position}, const char *@var{subr})
+@deftypefnx Macro void SCM_ASSERT_TYPE (int @var{test}, SCM @var{obj}, unsigned int @var{position}, const char *@var{subr}, const char *@var{expected})
+If @var{test} is zero, signal a ``wrong type argument'' error,
+attributed to the subroutine named @var{subr}, operating on the value
+@var{obj}, which is the @var{position}'th argument of @var{subr}.
+
+In @code{SCM_ASSERT_TYPE}, @var{expected} is a C string describing the
+type of argument that was expected.
+@end deftypefn
+
+@deftypefn Macro int SCM_ARG1
+@deftypefnx Macro int SCM_ARG2
+@deftypefnx Macro int SCM_ARG3
+@deftypefnx Macro int SCM_ARG4
+@deftypefnx Macro int SCM_ARG5
+@deftypefnx Macro int SCM_ARG6
+@deftypefnx Macro int SCM_ARG7
+One of the above values can be used for @var{position} to indicate the
+number of the argument of @var{subr} which is being checked.
+Alternatively, a positive integer number can be used, which allows to
+check arguments after the seventh. However, for parameter numbers up to
+seven it is preferable to use @code{SCM_ARGN} instead of the
+corresponding raw number, since it will make the code easier to
+understand.
+@end deftypefn
+
+@deftypefn Macro int SCM_ARGn
+Passing a value of zero or @code{SCM_ARGn} for @var{position} allows to
+leave it unspecified which argument's type is incorrect. Again,
+@code{SCM_ARGn} should be preferred over a raw zero constant.
+@end deftypefn
+
+@node Continuation Barriers
+@subsection Continuation Barriers
+
+The non-local flow of control caused by continuations might sometimes
+not be wanted. You can use @code{with-continuation-barrier} to erect
+fences that continuations can not pass.
+
+@deffn {Scheme Procedure} with-continuation-barrier proc
+@deffnx {C Function} scm_with_continuation_barrier (proc)
+Call @var{proc} and return its result. Do not allow the invocation of
+continuations that would leave or enter the dynamic extent of the call
+to @code{with-continuation-barrier}. Such an attempt causes an error
+to be signaled.
+
+Throws (such as errors) that are not caught from within @var{proc} are
+caught by @code{with-continuation-barrier}. In that case, a short
+message is printed to the current error port and @code{#f} is returned.
+
+Thus, @code{with-continuation-barrier} returns exactly once.
+@end deffn
-For @code{scm_wrong_num_args}, @var{proc} should be a Scheme symbol
-which is the name of the procedure incorrectly invoked.
+@deftypefn {C Function} {void *} scm_c_with_continuation_barrier (void *(*func) (void *), void *data)
+Like @code{scm_with_continuation_barrier} but call @var{func} on
+@var{data}. When an error is caught, @code{NULL} is returned.
@end deftypefn