diff --git a/doc/ChangeLog b/doc/ChangeLog index 51b687bd8..d11246258 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,11 @@ +2001-05-19 Neil Jerram + + * posix.texi (Networking): Split existing material into new nodes + `Network Address Conversion' and `Network Databases'. + + * scheme-control.texi (Lazy Catch): Update doc for new constraint + that lazy-catch handlers are not allowed to return. + 2001-05-16 Neil Jerram * data-rep.texi, srfi-modules.texi (SRFI-14 Iterating Over diff --git a/doc/posix.texi b/doc/posix.texi index 12508cffd..e16d0307a 100644 --- a/doc/posix.texi +++ b/doc/posix.texi @@ -1542,18 +1542,18 @@ close a pipe, but doesn't return the status. @section Networking @menu -* Network Databases and Address Conversion:: +* Network Address Conversion:: +* Network Databases:: * Network Sockets and Communication:: @end menu -@node Network Databases and Address Conversion -@subsection Network Databases and Address Conversion +@node Network Address Conversion +@subsection Network Address Conversion This section describes procedures which convert internet addresses -and query various network databases. Care should be taken when using -the database routines since they are not reentrant. +between numeric and string formats. -@subsubsection Address Conversion +@subsubsection IPv4 Address Conversion @deffn primitive inet-aton address Convert an IPv4 Internet address from printable string @@ -1630,6 +1630,14 @@ the result is an integer with normal host byte ordering. @end lisp @end deffn + +@node Network Databases +@subsection Network Databases + +This section describes procedures which query various network databases. +Care should be taken when using the database routines since they are not +reentrant. + @subsubsection The Host Database A @dfn{host object} is a structure that represents what is known about a diff --git a/doc/scheme-control.texi b/doc/scheme-control.texi index b1e67d2c5..e69de29bb 100644 --- a/doc/scheme-control.texi +++ b/doc/scheme-control.texi @@ -1,843 +0,0 @@ -@page -@node Control Mechanisms -@chapter Controlling the Flow of Program Execution - -@menu -* begin:: Evaluating a sequence of expressions. -* if cond case:: Simple conditional evaluation. -* and or:: Conditional evaluation of a sequence. -* while do:: Iteration mechanisms. -* Continuations:: Continuations. -* Multiple Values:: Returning and accepting multiple values. -* Exceptions:: Throwing and catching exceptions. -* Error Reporting:: Procedures for signaling errors. -* Dynamic Wind:: Guarding against non-local entrance/exit. -@end menu - - -@node begin -@section Evaluating a Sequence of Expressions - -@c FIXME::martin: Review me! - -@c FIXME::martin: Maybe add examples? - -@cindex begin -@cindex sequencing -@cindex expression sequencing - -@code{begin} is used for grouping several expression together so that -they syntactically 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: - -@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. - -@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 -@code{begin}-expression. This expression type is used when the -expressions before the last one are evaluated for their side effects. -@end deffn - -@node if cond case -@section Simple Conditional Evaluation - -@c FIXME::martin: Review me! - -@c FIXME::martin: Maybe add examples? - -@cindex conditional evaluation -@cindex if -@cindex case -@cindex cond - -Guile provides three syntactic constructs for conditional evaluation. -@code{if} is the normal if-then-else expression (with an optional else -branch), @code{cond} is a conditional expression with multiple branches -and @code{case} branches if an expression has one of a set of constant -values. - -@deffn syntax if test consequent [alternate] -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 ignoret. 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. - -When @var{alternate} is omitted and the @var{test} evaluates to -@code{#f}, the value of the expression is not specified. -@end deffn - -@deffn syntax cond clause1 clause2 @dots{} -Each @code{cond}-clause must look like this: - -@lisp -(@var{test} @var{expression} @dots{}) -@end lisp - -where @var{test} and @var{expression} are arbitrary expression, or like -this - -@lisp -(@var{test} => @var{expression} -@end lisp - -where @var{expression} must evaluate to a procedure. - -The @var{test}s of the clauses are evaluated in order and as soon as one -of them evaluates to a true values, the corresponding @var{expression}s -are evaluated in order and the last value is returned as the value of -the @code{cond}-expression. For the @code{=>} clause type, -@var{expression} is evaluated and the resulting procedure is applied to -the value of @var{test}. The result of this procedure application is -then the result of the @code{cond}-expression. - -The @var{test} of the last @var{clause} may be the keyword @code{else}. -Then, if none of the preceding @var{test}s is true, the @var{expression}s following the @code{else} are evaluated to produce the result of the @code{cond}-expression. -@end deffn - -@deffn syntax case key clause1 clause2 @dots{} -@var{key} may be any expression, the @var{clause}s must have the form - -@lisp -((@var{datum1} @dots{}) @var{expr1} @var{expr2} @dots{}) -@end lisp - -and the last @var{clause} may have the form - -@lisp -(else @var{expr1} @var{expr2} @dots{}) -@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 -@code{eqv?}. When this comparison succeeds, the epression(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. - -If the @var{key} matches no @var{datum} and there is an -@code{else}-clause, the expressions following the @code{else} are -evaluated. If there is no such clause, the result of the expression is -unspecified. -@end deffn - - -@node and or -@section Conditional Evaluation of a Sequence of Expressions - -@c FIXME::martin: Review me! - -@c FIXME::martin: Maybe add examples? - -@code{and} and @code{or} evaluate all their arguments, similar to -@code{begin}, but evaluation stops as soon as one of the expressions -evaluates to false or true, respectively. - -@deffn syntax and expr @dots{} -Evaluate the @var{expr}s from left to right and stop evaluation as soon -as one expression evaluates to @code{#f}; the remaining expressions are -not evaluated. The value of the last evaluated expression is returned. -If no expression evaluates to @code{#f}, the value of the last -expression is returned. - -If used without expressions, @code{#t} is returned. -@end deffn - -@deffn syntax or expr @dots{} -Evaluate the @var{expr}s from left to right and stop evaluation as soon -as one expression evaluates to a true value (that is, a value different -from @code{#f}); the remaining expressions are not evaluated. The value -of the last evaluated expression is returned. If all expressions -evaluate to @code{#f}, @code{#f} is returned. - -If used without expressions, @code{#f} is returned. -@end deffn - - -@node while do -@section Iteration mechanisms - -@c FIXME::martin: Review me! - -@c FIXME::martin: Maybe add examples? - -@cindex iteration -@cindex looping -@cindex named let - -Scheme has only few iteration mechanisms, mainly because iteration in -Scheme programs is normally expressed using recursion. Nevertheless, -R5RS defines a construct for programming loops, calling @code{do}. In -addition, Guile has an explicit looping syntax called @code{while}. - -@deffn syntax do ((variable1 init1 step1) @dots{}) (test expr @dots{}) command @dots{} -The @var{init} expressions are evaluated and the @var{variables} are -bound to their values. Then looping starts with testing the @var{test} -expression. If @var{test} evaluates to a true value, the @var{expr} -following the @var{test} are evaluated and the value of the last -@var{expr} is returned as the value of the @code{do} expression. If -@var{test} evaluates to false, the @var{command}s are evaluated in -order, the @var{step}s are evaluated and stored into the @var{variables} -and the next iteration starts. - -Any of the @var{step} expressions may be omitted, so that the -corresponding variable is not changed during looping. -@end deffn - -@deffn syntax while cond body @dots{} -Evaluate all expressions in @var{body} in order, as long as @var{cond} -evaluates to a true value. The @var{cond} expression is tested before -every iteration, so that the body is not evaluated at all if @var{cond} -is @code{#f} right from the start. -@end deffn - -@cindex named let -Another very common way of expressing iteration in Scheme programs is -the use of the so-called @dfn{named let}. - -Named let is a variant of @code{let} which creates a procedure and calls -it in one step. Because of the newly created procedure, named let is -more powerful than @code{do}--it can be used for iteration, but also -for arbitrary recursion. - -@deffn syntax let variable bindings body -For the definition of @var{bindings} see the documentation about -@code{let} (@pxref{Local Bindings}). - -Named @code{let} works as follows: - -@itemize @bullet -@item -A new procedure which accepts as many arguments as are in @var{bindings} -is created and bound locally (using @code{let}) to @var{variable}. The -new procedure's formal argument names are the name of the -@var{variables}. - -@item -The @var{body} expressions are inserted into the newly created procedure. - -@item -The procedure is called with the @var{init} expressions as the formal -arguments. -@end itemize - -The next example implements a loop which iterates (by recursion) 1000 -times. - -@lisp -(let lp ((x 1000)) - (if (positive? x) - (lp (- x 1)) - x)) -@result{} -0 -@end lisp -@end deffn - - -@node Continuations -@section Continuations - -@cindex call/cc -@cindex call-with-current-continuation -The ability to explicitly capture continuations using -@code{call-with-current-continuation} (also often called @code{call/cc} -for short), and to invoke such continuations later any number of times, -and from any other point in a program, provides maybe the most powerful -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. - -The implementation of continuations in Guile is not as efficient as one -might hope, because it is constrained by the fact that Guile is designed -to cooperate with programs written in other languages, such as C, which -do not know about continuations. So continuations should be used when -there is no other simple way of achieving the desired behaviour, or -where the advantages of the elegant continuation mechanism outweigh the -need for optimum performance. If you find yourself using @code{call/cc} -for escape procedures and your program is running too slow, you might -want to use exceptions (@pxref{Exceptions}) instead. - -@rnindex call-with-current-continuation -@deffn primitive call-with-current-continuation proc -Capture the current continuation and call @var{proc} with the captured -continuation as the single argument. This continuation can then be -called with arbitrarily many arguments. Such a call will work like a -goto to the invocation location of -@code{call-with-current-continuation}, passing the arguments in a way -that they are returned by the call to -@code{call-with-current-continuation}. Since it is legal to store the -captured continuation in a variable or to pass it to other procedures, -it is possible that a procedure returns more than once, even if it is -called only one time. This can be confusing at times. -@end deffn - -@c FIXME::martin: Better example needed. -@lisp -(define kont #f) -(call-with-current-continuation - (lambda (k) - (set! kont k) - 1)) -@result{} -1 - -(kont 2) -@result{} -2 -@end lisp - - -@node Multiple Values -@section Returning and Accepting Multiple Values - -@c FIXME::martin: Review me! -@cindex multiple values -@cindex receive - -Scheme allows a procedure to return more than one value to its caller. -This is quite different to other languages which only allow -single-value returns. Returning multiple values is different from -returning a list (or pair or vector) of values to the caller, because -conceptionally not @emph{one} compound object is returned, but several -distinct values. - -The primitive procedures for handling multiple values are @code{values} -and @code{call-with-values}. @code{values} is used for returning -multiple values from a procedure. This is done by placing a call to -@code{values} with zero or more arguments in tail position in a -procedure body. @code{call-with-values} combines a procedure returning -multiple values with a procedure which accepts these values as -parameters. - -@rnindex values -@deffn primitive values expr @dots{} -Delivers all of its arguments to its continuation. Except for -continuations created by the @code{call-with-values} procedure, -all continuations take exactly one value. The effect of -passing no value or more than one value to continuations that -were not created by @code{call-with-values} is unspecified. -@end deffn - -@rnindex call-with-values -@deffn primitive call-with-values producer consumer -Calls its @var{producer} argument with no values and a -continuation that, when passed some values, calls the -@var{consumer} procedure with those values as arguments. The -continuation for the call to @var{consumer} is the continuation -of the call to @code{call-with-values}. - -@example -(call-with-values (lambda () (values 4 5)) - (lambda (a b) b)) - ==> 5 - -@end example -@example -(call-with-values * -) ==> -1 -@end example -@end deffn - -In addition to the fundamental procedures described above, Guile has a -module which exports a syntax called @code{receive}, which is much more -convenient. If you want to use it in your programs, you have to load -the module @code{(ice-9 receive)} with the statement - -@lisp -(use-modules (ice-9 receive)) -@end lisp - -@deffn {library syntax} receive formals expr body @dots{} -Evaluate the expression @var{expr}, and bind the result values (zero or -more) to the formal arguments in the formal argument list @var{formals}. -@var{formals} must have the same syntax like the formal argument list -used in @code{lambda} (@pxref{Lambda}). After binding the variables, -the expressions in @var{body} @dots{} are evaluated in order. -@end deffn - - -@node Exceptions -@section Exceptions -@cindex error handling -@cindex exception handling - -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: - -@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 -* Exception Terminology:: Different ways to say the same thing. -* Catch:: Setting up to catch exceptions. -* Throw:: Throwing an exception. -* Lazy Catch:: Catch without unwinding the stack. -* Exception Implementation:: How Guile implements exceptions. -@end menu - - -@node Exception Terminology -@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 -Invoke @var{thunk} in the dynamic context of @var{handler} for -exceptions matching @var{key}. If thunk throws to the symbol -@var{key}, then @var{handler} is invoked this way: -@lisp -(handler key args ...) -@end lisp - -@var{key} is a symbol or @code{#t}. - -@var{thunk} takes no arguments. If @var{thunk} returns -normally, that is the return value of @code{catch}. - -Handler is invoked outside the scope of its own @code{catch}. -If @var{handler} again throws to the same key, a new handler -from further up the call chain is invoked. - -If the key is @code{#t}, then a throw to @emph{any} symbol will -match this call to @code{catch}. -@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 - -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 primitive 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} expression that applies to the type of the thrown -exception; in other words, the innermost @code{catch} whose @var{key} is -@code{#t} or is the same symbol as that used in the @code{throw} -expression. Once Guile has identified the appropriate @code{catch}, it -handles the exception by applying that @code{catch} expression's handler -procedure to the arguments of the @code{throw}. - -If there is no appropriate @code{catch} 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) -:3:1: In procedure gsubr-apply @dots{} -: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 Lazy Catch -@subsection Catch Without Unwinding - -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 -two important respects. - -@itemize @bullet -@item -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. - -@item -If the handler returns normally --- i.e. does not @emph{itself} throw an -exception --- then the @code{throw} expression returns normally to its -caller with the handler's value. -@end itemize - -@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 -handler returns, its value is returned from the throw. -@end deffn - -The net result is 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}, 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, if 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. On the other hand, if the -handler returns normally, the dynamic context is wound back to that of -the @code{throw} expression before passing the handler's return value to -the continuation of the @code{throw}. - -In most cases where @code{lazy-catch} is used, the handler does indeed -throw another exception, which is caught by a higher-level @code{catch}. -But this pattern is not mandatory, and it can be useful for the handler -to return normally. In the following example, the @code{lazy-catch} -handler is called twice and the results of the two calls added together. - -@lisp -(lazy-catch 'foo - (lambda () - (+ (throw 'foo 1) - (throw 'foo 2))) - (lambda args - (cadr args))) -@result{} -3 -@end lisp - -To see the point about dynamic context, consider the case where the -normal case thunk uses @code{with-fluids} (REFFIXME) 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. - - -@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 - -Guile provides a set of convenience procedures for signaling error -conditions that are implemented on top of the exception primitives just -described. - -@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 - -@deffn primitive scm-error key subr message args data -Raise an error with key @var{key}. @var{subr} can be a string -naming the procedure associated with the error, or @code{#f}. -@var{message} is the error message string, possibly containing -@code{~S} and @code{~A} escapes. When an error is reported, -these are replaced by formatting the corresponding members of -@var{args}: @code{~A} (was @code{%s} in older versions of -Guile) formats using @code{display} and @code{~S} (was -@code{%S}) formats using @code{write}. @var{data} is a list or -@code{#f} depending on @var{key}: if @var{key} is -@code{system-error} then it should be a list containing the -Unix @code{errno} value; If @var{key} is @code{signal} then it -should be a list containing the Unix signal number; otherwise -it will usually be @code{#f}. -@end deffn - -@deffn primitive strerror err -Return the Unix error message corresponding to @var{err}, which -must be an integer value. -@end deffn - -@c begin (scm-doc-string "boot-9.scm" "false-if-exception") -@deffn syntax false-if-exception expr -Returns the result of evaluating its argument; however -if an exception occurs then @code{#f} is returned instead. -@end deffn -@c end - - -@node Dynamic Wind -@section Dynamic Wind - -[FIXME: this is pasted in from Tom Lord's original guile.texi and should -be reviewed] - -@rnindex dynamic-wind -@deffn primitive dynamic-wind in_guard thunk out_guard -All three arguments must be 0-argument procedures. -@var{in_guard} is called, then @var{thunk}, then -@var{out_guard}. - -If, any time during the execution of @var{thunk}, the -continuation of the @code{dynamic_wind} expression is escaped -non-locally, @var{out_guard} is called. If the continuation of -the dynamic-wind is re-entered, @var{in_guard} is called. Thus -@var{in_guard} and @var{out_guard} may be called any number of -times. -@lisp -(define x 'normal-binding) -@result{} x -(define a-cont (call-with-current-continuation - (lambda (escape) - (let ((old-x x)) - (dynamic-wind - ;; in-guard: - ;; - (lambda () (set! x 'special-binding)) - - ;; thunk - ;; - (lambda () (display x) (newline) - (call-with-current-continuation escape) - (display x) (newline) - x) - - ;; out-guard: - ;; - (lambda () (set! x old-x))))))) - -;; Prints: -special-binding -;; Evaluates to: -@result{} a-cont -x -@result{} normal-binding -(a-cont #f) -;; Prints: -special-binding -;; Evaluates to: -@result{} a-cont ;; the value of the (define a-cont...) -x -@result{} normal-binding -a-cont -@result{} special-binding -@end lisp -@end deffn -@c Local Variables: -@c TeX-master: "guile.texi" -@c End: