1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-09 15:10:29 +02:00
guile/doc/scheme-control.texi
Martin Grabmüller 65f7a6501c * scheme-control.texi (while do): Added documentation for named
let.

	* scheme-binding.texi (Internal Definitions): New explanation of
	`Internal Definitions'.
	(Top Level): Documented behaviour of top level definitions.
	(Binding Constructs): New introductory text.
	(Local Bindings): Explain concept of local bindings.  Document
	let, let* and letrec.

	* scheme-modules.texi (Modules): Added menu descriptions.
	(Scheme and modules, The Guile module system): Some whitespace
	cleanup
	(The Guile module system): Layout fixes, docstring fix for
	`define-module'.
2001-04-19 21:35:44 +00:00

473 lines
16 KiB
Text

@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
@rnindex 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
@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
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.
@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
@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
@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
@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: