@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 @node if cond case @section Simple Conditional Evaluation @node and or @section Conditional Evaluation of a Sequence of Expressions @node while do @section Iteration mechanisms @node Continuations @section Continuations @r5index call-with-current-continuation @c FIXME::martin: Document me! @deffn primitive call-with-current-continuation @end deffn @node Multiple Values @section Returning and Accepting Multiple Values @r5index values @deffn primitive values . args 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 @r5index 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 @node Exceptions @section Exceptions @cindex error handling @cindex exception handling It is traditional in Scheme to implement exception systems using @code{call-with-current-continuation}. Guile does not do this, for performance reasons. The implementation of @code{call-with-current-continuation} is a stack copying implementation. This allows it to interact well with ordinary C code. Unfortunately, a stack-copying implementation can be slow -- creating a new continuation involves a block copy of the stack. Instead of using @code{call-with-current-continuation}, the exception primitives documented here are implemented as built-ins that take advantage of the @emph{upward only} nature of exceptions. @c docstring begin (texi-doc-string "guile" "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 @c docstring begin (texi-doc-string "guile" "throw") @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 #t. If there is no handler at all, an error is signaled. @end deffn @c docstring begin (texi-doc-string "guile" "lazy-catch") @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 @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. @c begin (scm-doc-string "boot-9.scm" "error") @deffn procedure error msg args @dots{} Raise an error with key @code{misc-error} and a message constructed by displaying @var{msg} and writing @var{args}. @end deffn @c end @c docstring begin (texi-doc-string "guile" "scm-error") @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 @c docstring begin (texi-doc-string "guile" "strerror") @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] @r5index dynamic-wind @c docstring begin (texi-doc-string "guile" "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: