123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376 |
- @c -*-texinfo-*-
- @c This is part of the GNU Guile Reference Manual.
- @c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010,
- @c 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
- @c See the file guile.texi for copying conditions.
- @node Control Mechanisms
- @section Controlling the Flow of Program Execution
- See @ref{Control Flow} for a discussion of how the more general control
- flow of Scheme affects C code.
- @menu
- * begin:: Sequencing and splicing.
- * Conditionals:: If, when, unless, case, and cond.
- * and or:: Conditional evaluation of a sequence.
- * while do:: Iteration mechanisms.
- * Prompts:: Composable, delimited continuations.
- * Continuations:: Non-composable continuations.
- * Multiple Values:: Returning and accepting multiple values.
- * Exceptions:: Raising and handling exceptions.
- * Error Reporting:: Procedures for signaling errors.
- * Dynamic Wind:: Dealing with non-local entrance/exit.
- * Fluids and Dynamic States:: Dynamic scope building blocks.
- * Parameters:: A dynamic scope facility.
- * Handling Errors:: How to handle errors in C code.
- * Continuation Barriers:: Protection from non-local control flow.
- @end menu
- @node begin
- @subsection Sequencing and Splicing
- @cindex begin
- @cindex sequencing
- @cindex expression sequencing
- 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 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 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.
- @end deffn
- @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
- 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 ignored. If @var{test} evaluates to
- @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:
- @lisp
- (@var{test} @var{expression} @dots{})
- @end lisp
- where @var{test} and @var{expression} are arbitrary expressions, 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 value, 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.
- @cindex SRFI-61
- @cindex general cond clause
- @cindex multiple values and cond
- One additional @code{cond}-clause is available as an extension to
- standard Scheme:
- @lisp
- (@var{test} @var{guard} => @var{expression})
- @end lisp
- where @var{guard} and @var{expression} must evaluate to procedures.
- For this clause type, @var{test} may return multiple values, and
- @code{cond} ignores its boolean state; instead, @code{cond} evaluates
- @var{guard} and applies the resulting procedure to the value(s) of
- @var{test}, as if @var{guard} were the @var{consumer} argument of
- @code{call-with-values}. If the result of that procedure call is a
- true value, it evaluates @var{expression} and applies the resulting
- procedure to the value(s) of @var{test}, in the same manner as the
- @var{guard} was called.
- The @var{test} of the last @var{clause} may be the symbol @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, 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
- 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.
- 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.
- 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
- @node and or
- @subsection Conditional Evaluation of a Sequence of Expressions
- @code{and} and @code{or} evaluate all their arguments in order, 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
- @subsection Iteration mechanisms
- @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 ((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,
- @example
- (do ((i 1 (1+ i)))
- ((> i 4))
- (display i))
- @print{} 1234
- @end example
- @noindent
- Or with two variables and a final return value,
- @example
- (do ((i 1 (1+ i))
- (p 3 (* 3 p)))
- ((> i 4)
- p)
- (format #t "3**~s is ~s\n" i p))
- @print{}
- 3**1 is 3
- 3**2 is 9
- 3**3 is 27
- 3**4 is 81
- @result{}
- 789
- @end example
- The @var{variable} bindings are established like a @code{let}, in that
- the expressions are all evaluated and then all bindings made. When
- iterating, the optional @var{step} expressions are evaluated with the
- previous bindings in scope, then new bindings all made.
- The @var{test} expression is a termination condition. Looping stops
- when the @var{test} is true. It's evaluated before running the
- @var{body} each time, so if it's true the first time then @var{body}
- is not run at all.
- The optional @var{expr}s after the @var{test} are evaluated at the end
- of looping, with the final @var{variable} bindings available. The
- last @var{expr} gives the return value, or if there are no @var{expr}s
- the return value is unspecified.
- Each iteration establishes bindings to fresh locations for the
- @var{variable}s, like a new @code{let} for each iteration. This is
- done for @var{variable}s without @var{step} expressions too. The
- following illustrates this, showing how a new @code{i} is captured by
- the @code{lambda} in each iteration (@pxref{About Closure,, The
- Concept of Closure}).
- @example
- (define lst '())
- (do ((i 1 (1+ i)))
- ((> i 4))
- (set! lst (cons (lambda () i) lst)))
- (map (lambda (proc) (proc)) lst)
- @result{}
- (4 3 2 1)
- @end example
- @end deffn
- @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.
- Within @code{while}, two extra bindings are provided, they can be used
- from both @var{cond} and @var{body}.
- @deffn {Scheme Procedure} break break-arg @dots{}
- Break out of the @code{while} form.
- @end deffn
- @deffn {Scheme Procedure} continue
- Abandon the current iteration, go back to the start and test
- @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.
- For example,
- @example
- (while (test1)
- (let ((outer-break break))
- (while (test2)
- (if (something)
- (outer-break #f))
- ...)))
- @end example
- Note that each @code{break} and @code{continue} procedure can only be
- used within the dynamic extent of its @code{while}. Outside the
- @code{while} their behaviour is unspecified.
- @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 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{with-exception-handler} and
- @code{raise-exception} 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.
- @cindex continuation, escape
- One example where this optimization matters is @dfn{escape
- continuations}. Escape continuations are delimited continuations whose
- only use is to make a non-local exit---i.e., to escape from the current
- continuation. A common use of escape continuations is when handling an
- exception (@pxref{Exceptions}).
- The constructs below are syntactic sugar atop prompts to simplify the
- use of escape continuations.
- @deffn {Scheme Procedure} call-with-escape-continuation proc
- @deffnx {Scheme Procedure} call/ec proc
- Call @var{proc} with an escape continuation.
- In the example below, the @var{return} continuation is used to escape
- the continuation of the call to @code{fold}.
- @lisp
- (use-modules (ice-9 control)
- (srfi srfi-1))
- (define (prefix x lst)
- ;; Return all the elements before the first occurrence
- ;; of X in LST.
- (call/ec
- (lambda (return)
- (fold (lambda (element prefix)
- (if (equal? element x)
- (return (reverse prefix)) ; escape `fold'
- (cons element prefix)))
- '()
- lst))))
- (prefix 'a '(0 1 2 a 3 4 5))
- @result{} (0 1 2)
- @end lisp
- @end deffn
- @deffn {Scheme Syntax} let-escape-continuation k body @dots{}
- @deffnx {Scheme Syntax} let/ec k body @dots{}
- Bind @var{k} within @var{body} to an escape continuation.
- This is equivalent to
- @code{(call/ec (lambda (@var{k}) @var{body} @dots{}))}.
- @end deffn
- Additionally there is another helper primitive exported by @code{(ice-9
- control)}, so load up that module for @code{suspendable-continuation?}:
- @example
- (use-modules (ice-9 control))
- @end example
- @deffn {Scheme Procedure} suspendable-continuation? tag
- Return @code{#t} if a call to @code{abort-to-prompt} with the prompt tag
- @var{tag} would produce a delimited continuation that could be resumed
- later.
- Almost all continuations have this property. The exception is where
- some code between the @code{call-with-prompt} and the
- @code{abort-to-prompt} recursed through C for some reason, the
- @code{abort-to-prompt} will succeed but any attempt to resume the
- continuation (by calling it) would fail. This is because composing a
- saved continuation with the current continuation involves relocating the
- stack frames that were saved from the old stack onto a (possibly) new
- position on the new stack, and Guile can only do this for stack frames
- that it created for Scheme code, not stack frames created by the C
- compiler. It's a bit gnarly but if you stick with Scheme, you won't
- have any problem.
- If no prompt is found with the given tag, this procedure just returns
- @code{#f}.
- @end deffn
- @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 be 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
- A ``continuation'' is the code that will execute when a given function
- or expression returns. For example, consider
- @example
- (define (foo)
- (display "hello\n")
- (display (bar)) (newline)
- (exit))
- @end example
- The continuation from the call to @code{bar} comprises a
- @code{display} of the value returned, a @code{newline} and an
- @code{exit}. This can be expressed as a function of one argument.
- @example
- (lambda (r)
- (display r) (newline)
- (exit))
- @end example
- In Scheme, continuations are represented as special procedures just
- like this. The special property is that when a continuation is called
- it abandons the current program location and jumps directly to that
- represented by the continuation.
- A continuation is like a dynamic label, capturing at run-time a point
- in program execution, including all the nested calls that have lead to
- it (or rather the code that will execute when those calls return).
- Continuations are created with the following functions.
- @deffn {Scheme Procedure} call-with-current-continuation proc
- @deffnx {Scheme Procedure} call/cc proc
- @rnindex call-with-current-continuation
- Capture the current continuation and call @code{(@var{proc}
- @var{cont})} with it. The return value is the value returned by
- @var{proc}, or when @code{(@var{cont} @var{value})} is later invoked,
- the return is the @var{value} passed.
- Normally @var{cont} should be called with one argument, but when the
- location resumed is expecting multiple values (@pxref{Multiple
- Values}) then they should be passed as multiple arguments, for
- instance @code{(@var{cont} @var{x} @var{y} @var{z})}.
- @var{cont} may only be used from the same side of a continuation
- barrier as it was created (@pxref{Continuation Barriers}), and in a
- multi-threaded program only from the thread in which it was created.
- The call to @var{proc} is not part of the continuation captured, it runs
- only when the continuation is created. Often a program will want to
- store @var{cont} somewhere for later use; this can be done in
- @var{proc}.
- The @code{call} in the name @code{call-with-current-continuation}
- refers to the way a call to @var{proc} gives the newly created
- continuation. It's not related to the way a call is used later to
- invoke that continuation.
- @code{call/cc} is an alias for @code{call-with-current-continuation}.
- This is in common use since the latter is rather long.
- @end deffn
- @sp 1
- @noindent
- Here is a simple example,
- @example
- (define kont #f)
- (format #t "the return is ~a\n"
- (call/cc (lambda (k)
- (set! kont k)
- 1)))
- @result{} the return is 1
- (kont 2)
- @result{} the return is 2
- @end example
- @code{call/cc} captures a continuation in which the value returned is
- going to be displayed by @code{format}. The @code{lambda} stores this
- in @code{kont} and gives an initial return @code{1} which is
- displayed. The later invocation of @code{kont} resumes the captured
- point, but this time returning @code{2}, which is displayed.
- When Guile is run interactively, a call to @code{format} like this has
- an implicit return back to the read-eval-print loop. @code{call/cc}
- captures that like any other return, which is why interactively
- @code{kont} will come back to read more input.
- @sp 1
- C programmers may note that @code{call/cc} is like @code{setjmp} in
- the way it records at runtime a point in program execution. A call to
- a continuation is like a @code{longjmp} in that it abandons the
- present location and goes to the recorded one. Like @code{longjmp},
- the value passed to the continuation is the value returned by
- @code{call/cc} on resuming there. However @code{longjmp} can only go
- up the program stack, but the continuation mechanism can go anywhere.
- When a continuation is invoked, @code{call/cc} and subsequent code
- effectively ``returns'' a second time. It can be confusing to imagine
- a function returning more times than it was called. It may help
- instead to think of it being stealthily re-entered and then program
- flow going on as normal.
- @code{dynamic-wind} (@pxref{Dynamic Wind}) can be used to ensure setup
- and cleanup code is run when a program locus is resumed or abandoned
- through the continuation mechanism.
- @sp 1
- Continuations are a powerful mechanism, and can be used to implement
- almost any sort of control structure, such as loops, coroutines, or
- exception handlers.
- However the implementation of continuations in Guile is not as
- efficient as one might hope, because Guile is designed to cooperate
- with programs written in other languages, such as C, which do not know
- about continuations. Basically continuations are captured by a block
- copy of the stack, and resumed by copying back.
- 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 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).
- @node Multiple Values
- @subsection Returning and Accepting Multiple Values
- @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
- conceptually 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 {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,
- 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.
- For @code{scm_values}, @var{args} is a list of arguments and the
- return is a multiple-values object which the caller can return. In
- the current implementation that object shares structure with
- @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 a more 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
- 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))
- @result{} 5
- @end example
- @example
- (call-with-values * -)
- @result{} -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. This is in the @code{(ice-9 receive)} and is the
- same as specified by SRFI-8 (@pxref{SRFI-8}).
- @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 @var{formals}. @var{formals} is a
- list of symbols, like the argument list in a @code{lambda}
- (@pxref{Lambda}). After binding the variables, the expressions in
- @var{body} @dots{} are evaluated in order, the return value is the
- result from the last expression.
- For example getting results from @code{partition} in SRFI-1
- (@pxref{SRFI-1}),
- @example
- (receive (odds evens)
- (partition odd? '(7 4 2 8 3))
- (display odds)
- (display " and ")
- (display evens))
- @print{} (7 3) and (4 2 8)
- @end example
- @end deffn
- @node Exceptions
- @subsection Exceptions
- @cindex error handling
- @cindex exception handling
- What happens when things go wrong? Guile's exception facility exists to
- help answer this question, allowing programs to describe the problem and
- to handle the situation in a flexible way.
- When a program runs into a problem, such as division by zero, it will
- raise an exception. Sometimes exceptions get raised by Guile on a
- program's behalf. Sometimes a program will want to raise exceptions of
- its own. Raising an exception stops the current computation and instead
- invokes the current exception handler, passing it an exception object
- describing the unexpected situation.
- Usually an exception handler will unwind the computation back to some
- kind of safe point. 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, raise an exception
- @dots{}
- @end example
- In this case, @code{main-loop} can install an exception handler that
- would cause any exception raised inside @code{dispatch-key} to print a
- warning and jump back to the main loop.
- The following subsections go into more detail about exception objects,
- raising exceptions, and handling exceptions. It also presents a
- historical interface that was used in Guile's first 25 years and which
- won't be going away any time soon.
- @menu
- * Exception Objects:: What went wrong?
- * Raising and Handling Exceptions:: What to do when something goes wrong.
- * Throw and Catch:: An older approach to exceptions.
- * Exceptions and C:: Specialized interfaces for C.
- @end menu
- @node Exception Objects
- @subsubsection Exception Objects
- When Guile encounters an exceptional situation, it raises an exception,
- where the exception is an object that describes the exceptional
- situation. Exception objects are structured data, built on the record
- facility (@pxref{Records}).
- @deftp {Exception Type} &exception
- The base exception type. All exception objects are composed of
- instances of subtypes of @code{&exception}.
- @end deftp
- @deffn {Scheme Procedure} exception-type? obj
- Return true if @var{obj} is an exception type.
- @end deffn
- Exception types exist in a hierarchy. New exception types can be
- defined using @code{make-exception-type}.
- @deffn {Scheme Procedure} make-exception-type id parent field-names
- Return a new exception type named @var{id}, inheriting from
- @var{parent}, and with the fields whose names are listed in
- @var{field-names}. @var{field-names} must be a list of symbols and must
- not contain names already used by @var{parent} or one of its supertypes.
- @end deffn
- Exception type objects are record type objects, and as such, one can use
- @code{record-constructor} on an exception type to get its constructor.
- The constructor will take as many arguments as the exception has fields
- (including supertypes). @xref{Records}.
- However, @code{record-predicate} and @code{record-accessor} aren't
- usually what you want to use as exception type predicates and field
- accessors. The reason is, instances of exception types can be composed
- into @dfn{compound exceptions}. Exception accessors should pick out the
- specific component of a compound exception, and then access the field on
- that specific component.
- @deffn {Scheme Procedure} make-exception exceptions @dots{}
- Return an exception object composed of @var{exceptions}.
- @end deffn
- @deffn {Scheme Procedure} exception? obj
- Return true if @var{obj} is an exception object.
- @end deffn
- @deffn {Scheme Procedure} exception-predicate type
- Return a procedure that will return true if its argument is a simple
- exception that is an instance of @var{type}, or a compound exception
- composed of such an instance.
- @end deffn
- @deffn {Scheme Procedure} exception-accessor rtd proc
- Return a procedure that will tail-call @var{proc} on an instance of the
- exception type @var{rtd}, or on the component of a compound exception
- that is an instance of @var{rtd}.
- @end deffn
- Compound exceptions are useful to separately express the different
- aspects of a situation. For example, compound exceptions allow a
- programmer to say that ``this situation is a programming error, and also
- here's a useful message to show to the user, and here are some relevant
- objects that can give more information about the error''. This error
- could be composed of instances of the @code{&programming-error},
- @code{&message}, and @code{&irritants} exception types.
- The subtyping relationship in exceptions is useful to let
- different-but-similar situations to be treated the same; for example
- there are many varieties of programming errors (for example,
- divide-by-zero or type mismatches), but perhaps there are common ways
- that the user would like to handle them all, and that common way might
- be different than how one might handle an error originating outside the
- program (for example, a file-not-found error).
- The standard exception hierarchy in Guile takes its cues from R6RS,
- though the names of some of the types are different. @xref{rnrs
- exceptions}, for more details.
- To have access to Guile's exception type hierarchy, import the
- @code{(ice-9 exceptions)} module:
- @example
- (use-modules (ice-9 exceptions))
- @end example
- The following diagram gives an overview of the standard exception type
- hierarchy.
- @example
- &exception
- |- &warning
- |- &message
- |- &irritants
- |- &origin
- \- &error
- |- &external-error
- \- &programming-error
- |- &assertion-failure
- |- &non-continuable
- |- &implementation-restriction
- |- &lexical
- |- &syntax
- \- &undefined-variable
- @end example
- @deftp {Exception Type} &warning
- An exception type denoting warnings. These are usually raised using
- @code{#:continuable? #t}; see the @code{raise-exception} documentation
- for more.
- @end deftp
- @deffn {Scheme Procedure} make-warning
- @deffnx {Scheme Procedure} warning? obj
- Constructor and predicate for @code{&warning} exception objects.
- @end deffn
- @deftp {Exception Type} &message message
- An exception type that provides a message to display to the user.
- Usually used as a component of a compound exception.
- @end deftp
- @deffn {Scheme Procedure} make-exception-with-message message
- @deffnx {Scheme Procedure} exception-with-message? obj
- @deffnx {Scheme Procedure} exception-message exn
- Constructor, predicate, and accessor for @code{&message} exception
- objects.
- @end deffn
- @deftp {Exception Type} &irritants irritants
- An exception type that provides a list of objects that were unexpected
- in some way. Usually used as a component of a compound exception.
- @end deftp
- @deffn {Scheme Procedure} make-exception-with-irritants irritants
- @deffnx {Scheme Procedure} exception-with-irritants? obj
- @deffnx {Scheme Procedure} exception-irritants exn
- Constructor, predicate, and accessor for @code{&irritants} exception
- objects.
- @end deffn
- @deftp {Exception Type} &origin origin
- An exception type that indicates the origin of an exception, typically
- expressed as a procedure name, as a symbol. Usually used as a component
- of a compound exception.
- @end deftp
- @deffn {Scheme Procedure} make-exception-with-origin origin
- @deffnx {Scheme Procedure} exception-with-origin? obj
- @deffnx {Scheme Procedure} exception-origin exn
- Constructor, predicate, and accessor for @code{&origin} exception
- objects.
- @end deffn
- @deftp {Exception Type} &error
- An exception type denoting errors: situations that are not just
- exceptional, but wrong.
- @end deftp
- @deffn {Scheme Procedure} make-error
- @deffnx {Scheme Procedure} error? obj
- Constructor and predicate for @code{&error} exception objects.
- @end deffn
- @deftp {Exception Type} &external-error
- An exception type denoting errors that proceed from the interaction of
- the program with the world, for example a ``file not found'' error.
- @end deftp
- @deffn {Scheme Procedure} make-external-error
- @deffnx {Scheme Procedure} external-error? obj
- Constructor and predicate for @code{&external-error} exception objects.
- @end deffn
- @deftp {Exception Type} &programming-error
- An exception type denoting errors that proceed from inside a program:
- type mismatches and so on.
- @end deftp
- @deffn {Scheme Procedure} make-programming-error
- @deffnx {Scheme Procedure} programming-error? obj
- Constructor and predicate for @code{&programming-error} exception
- objects.
- @end deffn
- @deftp {Exception Type} &non-continuable
- An exception type denoting errors that proceed from inside a program:
- type mismatches and so on.
- @end deftp
- @deffn {Scheme Procedure} make-non-continuable-error
- @deffnx {Scheme Procedure} non-continuable-error? obj
- Constructor and predicate for @code{&non-continuable} exception objects.
- @end deffn
- @deftp {Exception Type} &lexical
- An exception type denoting lexical errors, for example unbalanced
- parentheses.
- @end deftp
- @deffn {Scheme Procedure} make-lexical-error
- @deffnx {Scheme Procedure} lexical-error? obj
- Constructor and predicate for @code{&lexical} exception objects.
- @end deffn
- @deftp {Exception Type} &syntax form subform
- An exception type denoting syntax errors, for example a @code{cond}
- expression with invalid syntax. The @var{form} field indicates the form
- containing the error, and @var{subform} indicates the unexpected
- subcomponent, or @code{#f} if unavailable.
- @end deftp
- @deffn {Scheme Procedure} make-syntax-error form subform
- @deffnx {Scheme Procedure} syntax-error? obj
- @deffnx {Scheme Procedure} syntax-error-form exn
- @deffnx {Scheme Procedure} syntax-error-subform exn
- Constructor, predicate, and accessors for @code{&syntax} exception
- objects.
- @end deffn
- @deftp {Exception Type} &undefined-variable
- An exception type denoting undefined variables.
- @end deftp
- @deffn {Scheme Procedure} make-undefine-variable-error
- @deffnx {Scheme Procedure} undefined-variable-error? obj
- Constructor and predicate for @code{&undefined-variable} exception
- objects.
- @end deffn
- Incidentally, the @code{(ice-9 exceptions)} module also includes a
- @code{define-exception-type} macro that can be used to conveniently add
- new exception types to the hierarchy.
- @deffn {Syntax} define-exception-type name parent @
- constructor predicate @
- (field accessor) @dots{}
- Define @var{name} to be a new exception type, inheriting from
- @var{parent}. Define @var{constructor} and @var{predicate} to be the
- exception constructor and predicate, respectively, and define an
- @var{accessor} for each @var{field}.
- @end deffn
- @node Raising and Handling Exceptions
- @subsubsection Raising and Handling Exceptions
- An exception object describes an exceptional situation. To bring that
- description to the attention of the user or to handle the situation
- programmatically, the first step is to @dfn{raise} the exception.
- @deffn {Scheme Procedure} raise-exception obj [#:continuable=#f]
- Raise an exception by invoking the current exception handler on
- @var{obj}. The handler is called with a continuation whose dynamic
- environment is that of the call to @code{raise}, except that the current
- exception handler is the one that was in place when the handler being
- called was installed.
- If @var{continuable?} is true, the handler is invoked in tail position
- relative to the @code{raise-exception} call. Otherwise if the handler
- returns, a non-continuable exception of type @code{&non-continuable} is
- raised in the same dynamic environment as the handler.
- @end deffn
- As the above description notes, Guile has a notion of a @dfn{current
- exception handler}. At the REPL, this exception handler may enter a
- recursive debugger; in a standalone program, it may simply print a
- representation of the error and exit.
- To establish an exception handler within the dynamic extent of a call,
- use @code{with-exception-handler}.
- @deffn {Scheme Procedure} with-exception-handler handler thunk @
- [#:unwind?=#f] [#:unwind-for-type=#t]
- Establish @var{handler}, a procedure of one argument, as the current
- exception handler during the dynamic extent of invoking @var{thunk}.
- If @code{raise-exception} is called during the dynamic extent of
- invoking @var{thunk}, @var{handler} will be invoked on the argument of
- @code{raise-exception}.
- @end deffn
- There are two kinds of exception handlers: unwinding and non-unwinding.
- By default, exception handlers are non-unwinding. Unless
- @code{with-exception-handler} was invoked with @code{#:unwind? #t},
- exception handlers are invoked within the continuation of the error,
- without unwinding the stack. The dynamic environment of the handler
- call will be that of the @code{raise-exception} call, with the
- difference that the current exception handler will be ``unwound'' to the
- \"outer\" handler (the one that was in place when the corresponding
- @code{with-exception-handler} was called).
- However, it's often the case that one would like to handle an exception
- by unwinding the computation to an earlier state and running the error
- handler there. After all, unless the @code{raise-exception} call is
- continuable, the exception handler needs to abort the continuation. To
- support this use case, if @code{with-exception-handler} was invoked with
- @code{#:unwind? #t} is true, @code{raise-exception} will first unwind
- the stack by invoking an @dfn{escape continuation} (@pxref{Prompt
- Primitives, @code{call/ec}}), and then invoke the handler with the
- continuation of the @code{with-exception-handler} call.
- Finally, one more wrinkle: for unwinding exception handlers, it can be
- useful to Guile if it can determine whether an exception handler would
- indeed handle a particular exception or not. This is especially the
- case for exceptions raised in resource-exhaustion scenarios like
- @code{stack-overflow} or @code{out-of-memory}, where you want to
- immediately shrink resource use before recovering. @xref{Stack
- Overflow}. For this purpose, the @code{#:unwind-for-type} keyword
- argument allows users to specify the kind of exception handled by an
- exception handler; if @code{#t}, all exceptions will be handled; if an
- exception type object, only exceptions of that type will be handled;
- otherwise if a symbol, only that exceptions with the given
- @code{exception-kind} will be handled.
- @node Throw and Catch
- @subsubsection Throw and Catch
- Guile only adopted @code{with-exception-handler} and
- @code{raise-exception} as its primary exception-handling facility in
- 2019. Before then, exception handling was fundamentally based on three
- other primitives with a somewhat more complex interface: @code{catch},
- @code{with-throw-handler}, and @code{throw}.
- @deffn {Scheme Procedure} catch key thunk handler [pre-unwind-handler]
- @deffnx {C Function} scm_catch_with_pre_unwind_handler (key, thunk, handler, pre_unwind_handler)
- @deffnx {C Function} scm_catch (key, thunk, handler)
- Establish an exception handler during the dynamic extent of the call to
- @var{thunk}. @var{key} is either @code{#t}, indicating that all
- exceptions should be handled, or a symbol, restricting the exceptions
- handled to those having the @var{key} as their @code{exception-kind}.
- If @var{thunk} executes normally, meaning without throwing any
- exceptions, the handler procedures are not called at all and the result
- of the @code{thunk} call is the result of the @code{catch}. Otherwise
- if an exception is thrown that matches @var{key}, @var{handler} is
- called with the continuation of the @code{catch} call.
- @end deffn
- Given the discussion from the previous section, it is most precise and
- concise to specify what @code{catch} does by expressing it in terms of
- @code{with-exception-handler}. Calling @code{catch} with the three
- arguments is the same as:
- @example
- (define (catch key thunk handler)
- (with-exception-handler
- (lambda (exn)
- (apply handler (exception-kind exn) (exception-args exn)))
- thunk
- #:unwind? #t
- #:unwind-for-type key))
- @end example
- By invoking @code{with-exception-handler} with @code{#:unwind? #t},
- @code{catch} sets up an escape continuation that will be invoked in an
- exceptional situation before the handler is called.
- If @code{catch} is called with four arguments, then the use of
- @var{thunk} should be replaced with:
- @example
- (lambda ()
- (with-throw-handler key thunk pre-unwind-handler))
- @end example
- As can be seen above, if a pre-unwind-handler is passed to @code{catch},
- it's like calling @code{with-throw-handler} inside the body thunk.
- @code{with-throw-handler} is the second of the older primitives, and is
- used to be able to intercept an exception that is being 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.
- @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}.
- @end deffn
- It's not possible to exactly express @code{with-throw-handler} in terms
- of @code{with-exception-handler}, but we can get close.
- @example
- (define (with-throw-handler key thunk handler)
- (with-exception-handler
- (lambda (exn)
- (when (or (eq? key #t) (eq? key (exception-kind exn)))
- (apply handler (exception-kind exn) (exception-args exn)))
- (raise-exception exn))
- thunk))
- @end example
- As you can see, unlike in the case of @code{catch}, the handler for
- @code{with-throw-handler} is invoked within the continuation of
- @code{raise-exception}, before unwinding the stack. If the throw
- handler returns normally, the exception will be re-raised, to be handled
- by the next exception handler.
- The special wrinkle of @code{with-throw-handler} that can't be shown
- above is that if invoking the handler causes a @code{raise-exception}
- instead of completing normally, the exception is thrown in the
- @emph{original} dynamic environment of the @code{raise-exception}. Any
- inner exception handler will get another shot at handling the exception.
- Here is an example to illustrate this behavior:
- @lisp
- (catch 'a
- (lambda ()
- (with-throw-handler 'b
- (lambda ()
- (catch 'a
- (lambda ()
- (throw 'b))
- inner-handler))
- (lambda (key . args)
- (throw 'a))))
- outer-handler)
- @end lisp
- @noindent
- This code will call @code{inner-handler} and then continue with the
- continuation of the inner @code{catch}.
- Finally, we get to @code{throw}, which is the older equivalent to
- @code{raise-exception}.
- @deffn {Scheme Procedure} throw key arg @dots{}
- @deffnx {C Function} scm_throw (key, args)
- Raise an exception with kind @var{key} and arguments @var{args}.
- @var{key} is a symbol, denoting the ``kind'' of the exception.
- @end deffn
- Again, we can specify what @code{throw} does by expressing it in terms
- of @code{raise-exception}.
- @example
- (define (throw key . args)
- (raise-exception (make-exception-from-throw key args)))
- @end example
- At this point, we should mention the primitive that manage the
- relationship between structured exception objects @code{throw}.
- @deffn {Scheme Procedure} make-exception-from-throw key args
- Create an exception object for the given @var{key} and @var{args} passed
- to @code{throw}. This may be a specific type of exception, for example
- @code{&programming-error}; Guile maintains a set of custom transformers
- for the various @var{key} values that have been used historically.
- @end deffn
- @deffn {Scheme Procedure} exception-kind exn
- If @var{exn} is an exception created via
- @code{make-exception-from-throw}, return the corresponding @var{key} for
- the exception. Otherwise, unless @var{exn} is an exception of a type
- with a known mapping to @code{throw}, return the symbol
- @code{%exception}.
- @end deffn
- @deffn {Scheme Procedure} exception-args exn
- If @var{exn} is an exception created via
- @code{make-exception-from-throw}, return the corresponding @var{args}
- for the exception. Otherwise, unless @var{exn} is an exception of a
- type with a known mapping to @code{throw}, return @code{(list @var{exn})}.
- @end deffn
- @node Exceptions and C
- @subsubsection Exceptions and C
- There are some specific versions of Guile's original @code{catch} and
- @code{with-throw-handler} exception-handling primitives that are still
- widely used in C code.
- @deftypefn {C Function} SCM scm_c_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data, scm_t_catch_handler pre_unwind_handler, void *pre_unwind_handler_data)
- @deftypefnx {C Function} SCM scm_internal_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data)
- The above @code{scm_catch_with_pre_unwind_handler} and @code{scm_catch}
- take Scheme procedures as body and handler arguments.
- @code{scm_c_catch} and @code{scm_internal_catch} are equivalents taking
- C functions.
- @var{body} is called as @code{@var{body} (@var{body_data})} with a catch
- on exceptions of the given @var{tag} type. If an exception is caught,
- @var{pre_unwind_handler} and @var{handler} are called as
- @code{@var{handler} (@var{handler_data}, @var{key}, @var{args})}.
- @var{key} and @var{args} are the @code{SCM} key and argument list from
- the @code{throw}.
- @tpindex scm_t_catch_body
- @tpindex scm_t_catch_handler
- @var{body} and @var{handler} should have the following prototypes.
- @code{scm_t_catch_body} and @code{scm_t_catch_handler} are pointer
- typedefs for these.
- @example
- SCM body (void *data);
- SCM handler (void *data, SCM key, SCM args);
- @end example
- The @var{body_data} and @var{handler_data} parameters are passed to
- the respective calls so an application can communicate extra
- information to those functions.
- If the data consists of an @code{SCM} object, care should be taken that
- it isn't garbage collected while still required. If the @code{SCM} is a
- local C variable, one way to protect it is to pass a pointer to that
- variable as the data parameter, since the C compiler will then know the
- value must be held on the stack. Another way is to use
- @code{scm_remember_upto_here_1} (@pxref{Foreign Object Memory
- Management}).
- @end deftypefn
- @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
- equivalent taking C functions. See @code{scm_c_catch}
- (@pxref{Exceptions and C}) for a description of the parameters, the
- behaviour however of course follows @code{with-throw-handler}.
- @end deftypefn
- @node Error Reporting
- @subsection 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 {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{arg} @enddots{}.
- @end deffn
- @deffn {Scheme Procedure} scm-error key subr message args data
- @deffnx {C Function} scm_error_scm (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; If
- @var{key} is @code{out-of-range}, @code{wrong-type-arg},
- or @code{keyword-argument-error},
- it is a list containing the bad value; otherwise
- it will usually be @code{#f}.
- @end deffn
- @deffn {Scheme Procedure} strerror err
- @deffnx {C Function} scm_strerror (err)
- Return the Unix error message corresponding to @var{err}, an integer
- @code{errno} value.
- When @code{setlocale} has been called (@pxref{Locales}), the message
- is in the language and charset of @code{LC_MESSAGES}. (This is done
- by the C library.)
- @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
- @subsection Dynamic Wind
- For Scheme code, the fundamental procedure to react to non-local entry
- and exits of dynamic contexts is @code{dynamic-wind}. C code could
- use @code{scm_internal_dynamic_wind}, but since C does not allow the
- convenient construction of anonymous procedures that close over
- lexical variables, this will be, well, inconvenient.
- Therefore, Guile offers the functions @code{scm_dynwind_begin} and
- @code{scm_dynwind_end} to delimit a dynamic extent. Within this
- dynamic extent, which is called a @dfn{dynwind context}, you can
- perform various @dfn{dynwind actions} that control what happens when
- the dynwind context is entered or left. For example, you can register
- a cleanup routine with @code{scm_dynwind_unwind_handler} that is
- executed when the context is left. There are several other more
- specialized dynwind actions as well, for example to temporarily block
- the execution of asyncs or to temporarily change the current output
- port. They are described elsewhere in this manual.
- Here is an example that shows how to prevent memory leaks.
- @example
- /* Suppose there is a function called FOO in some library that you
- would like to make available to Scheme code (or to C code that
- follows the Scheme conventions).
- FOO takes two C strings and returns a new string. When an error has
- occurred in FOO, it returns NULL.
- */
- char *foo (char *s1, char *s2);
- /* SCM_FOO interfaces the C function FOO to the Scheme way of life.
- It takes care to free up all temporary strings in the case of
- non-local exits.
- */
- SCM
- scm_foo (SCM s1, SCM s2)
- @{
- char *c_s1, *c_s2, *c_res;
- scm_dynwind_begin (0);
- c_s1 = scm_to_locale_string (s1);
- /* Call 'free (c_s1)' when the dynwind context is left.
- */
- scm_dynwind_unwind_handler (free, c_s1, SCM_F_WIND_EXPLICITLY);
- c_s2 = scm_to_locale_string (s2);
-
- /* Same as above, but more concisely.
- */
- scm_dynwind_free (c_s2);
- c_res = foo (c_s1, c_s2);
- if (c_res == NULL)
- scm_report_out_of_memory ();
- scm_dynwind_end ();
- return scm_take_locale_string (res);
- @}
- @end example
- @rnindex dynamic-wind
- @deffn {Scheme Procedure} dynamic-wind in_guard thunk out_guard
- @deffnx {C Function} scm_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
- dynamic extent of the @code{dynamic-wind} expression is escaped
- non-locally, @var{out_guard} is called. If the dynamic extent 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
- @deftp {C Type} scm_t_dynwind_flags
- This is an enumeration of several flags that modify the behavior of
- @code{scm_dynwind_begin}. The flags are listed in the following
- table.
- @table @code
- @item SCM_F_DYNWIND_REWINDABLE
- The dynamic context is @dfn{rewindable}. This means that it can be
- reentered non-locally (via the invocation of a continuation). The
- default is that a dynwind context can not be reentered non-locally.
- @end table
- @end deftp
- @deftypefn {C Function} void scm_dynwind_begin (scm_t_dynwind_flags flags)
- The function @code{scm_dynwind_begin} starts a new dynamic context and
- makes it the `current' one.
- The @var{flags} argument determines the default behavior of the
- context. Normally, use 0. This will result in a context that can not
- be reentered with a captured continuation. When you are prepared to
- handle reentries, include @code{SCM_F_DYNWIND_REWINDABLE} in
- @var{flags}.
- Being prepared for reentry means that the effects of unwind handlers
- can be undone on reentry. In the example above, we want to prevent a
- memory leak on non-local exit and thus register an unwind handler that
- frees the memory. But once the memory is freed, we can not get it
- back on reentry. Thus reentry can not be allowed.
- The consequence is that continuations become less useful when
- 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,
- or explicitly with @code{scm_dynwind_end}. You must make sure that a
- dynwind context is indeed ended properly. If you fail to call
- @code{scm_dynwind_end} for each @code{scm_dynwind_begin}, the behavior
- is undefined.
- @end deftypefn
- @deftypefn {C Function} void scm_dynwind_end ()
- End the current dynamic context explicitly and make the previous one
- current.
- @end deftypefn
- @deftp {C Type} scm_t_wind_flags
- This is an enumeration of several flags that modify the behavior of
- @code{scm_dynwind_unwind_handler} and
- @code{scm_dynwind_rewind_handler}. The flags are listed in the
- following table.
- @table @code
- @item SCM_F_WIND_EXPLICITLY
- @vindex SCM_F_WIND_EXPLICITLY
- The registered action is also carried out when the dynwind context is
- entered or left locally.
- @end table
- @end deftp
- @deftypefn {C Function} void scm_dynwind_unwind_handler (void (*func)(void *), void *data, scm_t_wind_flags flags)
- @deftypefnx {C Function} void scm_dynwind_unwind_handler_with_scm (void (*func)(SCM), SCM data, scm_t_wind_flags flags)
- Arranges for @var{func} to be called with @var{data} as its arguments
- when the current context ends implicitly. If @var{flags} contains
- @code{SCM_F_WIND_EXPLICITLY}, @var{func} is also called when the
- context ends explicitly with @code{scm_dynwind_end}.
- The function @code{scm_dynwind_unwind_handler_with_scm} takes care that
- @var{data} is protected from garbage collection.
- @end deftypefn
- @deftypefn {C Function} void scm_dynwind_rewind_handler (void (*func)(void *), void *data, scm_t_wind_flags flags)
- @deftypefnx {C Function} void scm_dynwind_rewind_handler_with_scm (void (*func)(SCM), SCM data, scm_t_wind_flags flags)
- Arrange for @var{func} to be called with @var{data} as its argument when
- the current context is restarted by rewinding the stack. When @var{flags}
- contains @code{SCM_F_WIND_EXPLICITLY}, @var{func} is called immediately
- as well.
- The function @code{scm_dynwind_rewind_handler_with_scm} takes care that
- @var{data} is protected from garbage collection.
- @end deftypefn
- @deftypefn {C Function} void scm_dynwind_free (void *mem)
- Arrange for @var{mem} to be freed automatically whenever the current
- context is exited, whether normally or non-locally.
- @code{scm_dynwind_free (mem)} is an equivalent shorthand for
- @code{scm_dynwind_unwind_handler (free, mem, SCM_F_WIND_EXPLICITLY)}.
- @end deftypefn
- @node Fluids and Dynamic States
- @subsection Fluids and Dynamic States
- @cindex fluids
- A @emph{fluid} is a variable whose value is associated with the dynamic
- extent of a function call. In the same way that an operating system
- runs a process with a given set of current input and output ports (or
- file descriptors), in Guile you can arrange to call a function while
- binding a fluid to a particular value. That association between fluid
- and value will exist during the dynamic extent of the function call.
- Fluids are therefore a building block for implementing dynamically
- scoped variables. Dynamically scoped variables are useful when you want
- to set a variable to a value during some dynamic extent in the execution
- of your program and have them revert to their original value when the
- control flow is outside of this dynamic extent. See the description of
- @code{with-fluids} below for details. This association between fluids,
- values, and dynamic extents is robust to multiple entries (as when a
- captured continuation is invoked more than once) and early exits (for
- example, when throwing exceptions).
- Guile uses fluids to implement parameters (@pxref{Parameters}). Usually
- you just want to use parameters directly. However it can be useful to
- know what a fluid is and how it works, so that's what this section is
- about.
- The current set of fluid-value associations can be captured in a
- @emph{dynamic state} object. A dynamic extent is simply that: a
- snapshot of the current fluid-value associations. Guile users can
- capture the current dynamic state with @code{current-dynamic-state} and
- restore it later via @code{with-dynamic-state} or similar procedures.
- This facility is especially useful when implementing lightweight
- thread-like abstractions.
- New fluids are created with @code{make-fluid} and @code{fluid?} is
- used for testing whether an object is actually a fluid. The values
- stored in a fluid can be accessed with @code{fluid-ref} and
- @code{fluid-set!}.
- @xref{Thread Local Variables}, for further notes on fluids, threads,
- parameters, and dynamic states.
- @deffn {Scheme Procedure} make-fluid [dflt]
- @deffnx {C Function} scm_make_fluid ()
- @deffnx {C Function} scm_make_fluid_with_default (dflt)
- Return a newly created fluid, whose initial value is @var{dflt}, or
- @code{#f} if @var{dflt} is not given.
- Fluids are objects that can hold one
- value per dynamic state. That is, modifications to this value are
- only visible to code that executes with the same dynamic state as
- the modifying code. When a new dynamic state is constructed, it
- inherits the values from its parent. Because each thread normally executes
- with its own dynamic state, you can use fluids for thread local storage.
- @end deffn
- @deffn {Scheme Procedure} make-unbound-fluid
- @deffnx {C Function} scm_make_unbound_fluid ()
- Return a new fluid that is initially unbound (instead of being
- implicitly bound to some definite value).
- @end deffn
- @deffn {Scheme Procedure} fluid? obj
- @deffnx {C Function} scm_fluid_p (obj)
- Return @code{#t} if @var{obj} is a fluid; otherwise, return
- @code{#f}.
- @end deffn
- @deffn {Scheme Procedure} fluid-ref fluid
- @deffnx {C Function} scm_fluid_ref (fluid)
- Return the value associated with @var{fluid} in the current
- dynamic root. If @var{fluid} has not been set, then return
- its default value. Calling @code{fluid-ref} on an unbound fluid produces
- a runtime error.
- @end deffn
- @deffn {Scheme Procedure} fluid-set! fluid value
- @deffnx {C Function} scm_fluid_set_x (fluid, value)
- Set the value associated with @var{fluid} in the current dynamic root.
- @end deffn
- @deffn {Scheme Procedure} fluid-ref* fluid depth
- @deffnx {C Function} scm_fluid_ref_star (fluid, depth)
- Return the @var{depth}th oldest value associated with @var{fluid} in the
- current thread. If @var{depth} equals or exceeds the number of values
- that have been assigned to @var{fluid}, return the default value of the
- fluid. @code{(fluid-ref* f 0)} is equivalent to @code{(fluid-ref f)}.
- @code{fluid-ref*} is useful when you want to maintain a stack-like
- structure in a fluid, such as the stack of current exception handlers.
- Using @code{fluid-ref*} instead of an explicit stack allows any partial
- continuation captured by @code{call-with-prompt} to only capture the
- bindings made within the limits of the prompt instead of the entire
- continuation. @xref{Prompts}, for more on delimited continuations.
- @end deffn
- @deffn {Scheme Procedure} fluid-unset! fluid
- @deffnx {C Function} scm_fluid_unset_x (fluid)
- Disassociate the given fluid from any value, making it unbound.
- @end deffn
- @deffn {Scheme Procedure} fluid-bound? fluid
- @deffnx {C Function} scm_fluid_bound_p (fluid)
- Returns @code{#t} if the given fluid is bound to a value, otherwise
- @code{#f}.
- @end deffn
- @code{with-fluids*} temporarily changes the values of one or more fluids,
- so that the given procedure and each procedure called by it access the
- given values. After the procedure returns, the old values are restored.
- @deffn {Scheme Procedure} with-fluid* fluid value thunk
- @deffnx {C Function} scm_with_fluid (fluid, value, thunk)
- Set @var{fluid} to @var{value} temporarily, and call @var{thunk}.
- @var{thunk} must be a procedure with no argument.
- @end deffn
- @deffn {Scheme Procedure} with-fluids* fluids values thunk
- @deffnx {C Function} scm_with_fluids (fluids, values, thunk)
- Set @var{fluids} to @var{values} temporary, and call @var{thunk}.
- @var{fluids} must be a list of fluids and @var{values} must be the
- same number of their values to be applied. Each substitution is done
- in the order given. @var{thunk} must be a procedure with no argument.
- It is called inside a @code{dynamic-wind} and the fluids are
- set/restored when control enter or leaves the established dynamic
- extent.
- @end deffn
- @deffn {Scheme Macro} with-fluids ((fluid value) @dots{}) body1 body2 @dots{}
- Execute body @var{body1} @var{body2} @dots{} while each @var{fluid} is
- set to the corresponding @var{value}. Both @var{fluid} and @var{value}
- are evaluated and @var{fluid} must yield a fluid. The body is executed
- inside a @code{dynamic-wind} and the fluids are set/restored when
- control enter or leaves the established dynamic extent.
- @end deffn
- @deftypefn {C Function} SCM scm_c_with_fluids (SCM fluids, SCM vals, SCM (*cproc)(void *), void *data)
- @deftypefnx {C Function} SCM scm_c_with_fluid (SCM fluid, SCM val, SCM (*cproc)(void *), void *data)
- The function @code{scm_c_with_fluids} is like @code{scm_with_fluids}
- except that it takes a C function to call instead of a Scheme thunk.
- The function @code{scm_c_with_fluid} is similar but only allows one
- fluid to be set instead of a list.
- @end deftypefn
- @deftypefn {C Function} void scm_dynwind_fluid (SCM fluid, SCM val)
- This function must be used inside a pair of calls to
- @code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic
- Wind}). During the dynwind context, the fluid @var{fluid} is set to
- @var{val}.
- More precisely, the value of the fluid is swapped with a `backup'
- value whenever the dynwind context is entered or left. The backup
- value is initialized with the @var{val} argument.
- @end deftypefn
- @deffn {Scheme Procedure} dynamic-state? obj
- @deffnx {C Function} scm_dynamic_state_p (obj)
- Return @code{#t} if @var{obj} is a dynamic state object;
- return @code{#f} otherwise.
- @end deffn
- @deftypefn {C Procedure} int scm_is_dynamic_state (SCM obj)
- Return non-zero if @var{obj} is a dynamic state object;
- return zero otherwise.
- @end deftypefn
- @deffn {Scheme Procedure} current-dynamic-state
- @deffnx {C Function} scm_current_dynamic_state ()
- Return a snapshot of the current fluid-value associations as a fresh
- dynamic state object.
- @end deffn
- @deffn {Scheme Procedure} set-current-dynamic-state state
- @deffnx {C Function} scm_set_current_dynamic_state (state)
- Restore the saved fluid-value associations from @var{state}, replacing
- the current fluid-value associations. Return the current fluid-value
- associatoins as a dynamic state object, as in
- @code{current-dynamic-state}.
- @end deffn
- @deffn {Scheme Procedure} with-dynamic-state state proc
- @deffnx {C Function} scm_with_dynamic_state (state, proc)
- Call @var{proc} while the fluid bindings from @var{state} have been made
- current, saving the current fluid bindings. When control leaves the
- invocation of @var{proc}, restore the saved bindings, saving instead the
- fluid bindings from inside the call. If control later re-enters
- @var{proc}, restore those saved bindings, saving the current bindings,
- and so on.
- @end deffn
- @deftypefn {C Procedure} void scm_dynwind_current_dynamic_state (SCM state)
- Set the current dynamic state to @var{state} for the current dynwind
- context. Like @code{with-dynamic-state}, but in terms of Guile's
- ``dynwind'' C API.
- @end deftypefn
- @deftypefn {C Procedure} {void *} scm_c_with_dynamic_state (SCM state, void *(*func)(void *), void *data)
- Like @code{scm_with_dynamic_state}, but call @var{func} with
- @var{data}.
- @end deftypefn
- @node Parameters
- @subsection Parameters
- @cindex SRFI-39
- @cindex parameter object
- @tindex Parameter
- Parameters are Guile's facility for dynamically bound variables.
- On the most basic level, a parameter object is a procedure. Calling it
- with no arguments returns its value. Calling it with one argument sets
- the value.
- @example
- (define my-param (make-parameter 123))
- (my-param) @result{} 123
- (my-param 456)
- (my-param) @result{} 456
- @end example
- The @code{parameterize} special form establishes new locations for
- parameters, those new locations having effect within the dynamic extent
- of the @code{parameterize} body. Leaving restores the previous
- locations. Re-entering (through a saved continuation) will again use
- the new locations.
- @example
- (parameterize ((my-param 789))
- (my-param)) @result{} 789
- (my-param) @result{} 456
- @end example
- Parameters are like dynamically bound variables in other Lisp dialects.
- They allow an application to establish parameter settings (as the name
- suggests) just for the execution of a particular bit of code, restoring
- when done. Examples of such parameters might be case-sensitivity for a
- search, or a prompt for user input.
- Global variables are not as good as parameter objects for this sort of
- thing. Changes to them are visible to all threads, but in Guile
- parameter object locations are per-thread, thereby truly limiting the
- effect of @code{parameterize} to just its dynamic execution.
- Passing arguments to functions is thread-safe, but that soon becomes
- tedious when there's more than a few or when they need to pass down
- through several layers of calls before reaching the point they should
- affect. Introducing a new setting to existing code is often easier with
- a parameter object than adding arguments.
- @deffn {Scheme Procedure} make-parameter init [converter]
- Return a new parameter object, with initial value @var{init}.
- If a @var{converter} is given, then a call @code{(@var{converter}
- val)} is made for each value set, its return is the value stored.
- Such a call is made for the @var{init} initial value too.
- A @var{converter} allows values to be validated, or put into a
- canonical form. For example,
- @example
- (define my-param (make-parameter 123
- (lambda (val)
- (if (not (number? val))
- (error "must be a number"))
- (inexact->exact val))))
- (my-param 0.75)
- (my-param) @result{} 3/4
- @end example
- @end deffn
- @deffn {library syntax} parameterize ((param value) @dots{}) body1 body2 @dots{}
- Establish a new dynamic scope with the given @var{param}s bound to new
- locations and set to the given @var{value}s. @var{body1} @var{body2}
- @dots{} is evaluated in that environment. The value returned is that of
- last body form.
- Each @var{param} is an expression which is evaluated to get the
- parameter object. Often this will just be the name of a variable
- holding the object, but it can be anything that evaluates to a
- parameter.
- The @var{param} expressions and @var{value} expressions are all
- evaluated before establishing the new dynamic bindings, and they're
- evaluated in an unspecified order.
- For example,
- @example
- (define prompt (make-parameter "Type something: "))
- (define (get-input)
- (display (prompt))
- ...)
- (parameterize ((prompt "Type a number: "))
- (get-input)
- ...)
- @end example
- @end deffn
- Parameter objects are implemented using fluids (@pxref{Fluids and
- Dynamic States}), so each dynamic state has its own parameter
- locations. That includes the separate locations when outside any
- @code{parameterize} form. When a parameter is created it gets a
- separate initial location in each dynamic state, all initialized to the
- given @var{init} value.
- New code should probably just use parameters instead of fluids, because
- the interface is better. But for migrating old code or otherwise
- providing interoperability, Guile provides the @code{fluid->parameter}
- procedure:
- @deffn {Scheme Procedure} fluid->parameter fluid [conv]
- Make a parameter that wraps a fluid.
- The value of the parameter will be the same as the value of the fluid.
- If the parameter is rebound in some dynamic extent, perhaps via
- @code{parameterize}, the new value will be run through the optional
- @var{conv} procedure, as with any parameter. Note that unlike
- @code{make-parameter}, @var{conv} is not applied to the initial value.
- @end deffn
- As alluded to above, because each thread usually has a separate dynamic
- state, each thread has its own locations behind parameter objects, and
- changes in one thread are not visible to any other. When a new dynamic
- state or thread is created, the values of parameters in the originating
- context are copied, into new locations.
- @cindex SRFI-39
- Guile's parameters conform to SRFI-39 (@pxref{SRFI-39}).
- @node Handling Errors
- @subsection How to Handle Errors
- Guile is currently in a transition from its historical @code{catch} and
- @code{throw} error handling and signaling operators to the new
- structured exception facility; @xref{Exceptions}. However in the
- meantime, here is some documentation on errors and the older
- @code{catch} and @code{throw} interface.
- Errors are always thrown with a @var{key} and four arguments:
- @itemize @bullet
- @item
- @var{key}: a symbol which indicates the type of error. The symbols used
- by libguile are listed below.
- @item
- @var{subr}: the name of the procedure from which the error is thrown, or
- @code{#f}.
- @item
- @var{message}: a string (possibly language and system dependent)
- describing the error. The tokens @code{~A} and @code{~S} can be
- embedded within the message: they will be replaced with members of the
- @var{args} list when the message is printed. @code{~A} indicates an
- argument printed using @code{display}, while @code{~S} indicates an
- argument printed using @code{write}. @var{message} can also be
- @code{#f}, to allow it to be derived from the @var{key} by the error
- handler (may be useful if the @var{key} is to be thrown from both C and
- Scheme).
- @item
- @var{args}: a list of arguments to be used to expand @code{~A} and
- @code{~S} tokens in @var{message}. Can also be @code{#f} if no
- arguments are required.
- @item
- @var{rest}: a list of any additional objects required. e.g., when the
- key is @code{'system-error}, this contains the C errno value. Can also
- be @code{#f} if no additional objects are required.
- @end itemize
- In addition to @code{catch} and @code{throw}, the following Scheme
- facilities are available:
- @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{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
- the list @var{args} accordingly. @var{rest} is currently
- ignored.
- @end deffn
- The following are the error keys defined by libguile and the situations
- in which they are used:
- @itemize @bullet
- @item
- @cindex @code{error-signal}
- @code{error-signal}: thrown after receiving an unhandled fatal signal
- such as SIGSEGV, SIGBUS, SIGFPE etc. The @var{rest} argument in the throw
- contains the coded signal number (at present this is not the same as the
- usual Unix signal number).
- @item
- @cindex @code{system-error}
- @code{system-error}: thrown after the operating system indicates an
- error condition. The @var{rest} argument in the throw contains the
- errno value.
- @item
- @cindex @code{numerical-overflow}
- @code{numerical-overflow}: numerical overflow.
- @item
- @cindex @code{out-of-range}
- @code{out-of-range}: the arguments to a procedure do not fall within the
- accepted domain.
- @item
- @cindex @code{wrong-type-arg}
- @code{wrong-type-arg}: an argument to a procedure has the wrong type.
- @item
- @cindex @code{wrong-number-of-args}
- @code{wrong-number-of-args}: a procedure was called with the wrong number
- of arguments.
- @item
- @cindex @code{memory-allocation-error}
- @code{memory-allocation-error}: memory allocation error.
- @item
- @cindex @code{stack-overflow}
- @code{stack-overflow}: stack overflow error.
- @item
- @cindex @code{regular-expression-syntax}
- @code{regular-expression-syntax}: errors generated by the regular
- expression library.
- @item
- @cindex @code{misc-error}
- @code{misc-error}: other errors.
- @end itemize
- @subsubsection C Support
- In the following C functions, @var{SUBR} and @var{MESSAGE} parameters
- can be @code{NULL} to give the effect of @code{#f} described above.
- @deftypefn {C Function} SCM scm_error (SCM @var{key}, char *@var{subr}, char *@var{message}, SCM @var{args}, SCM @var{rest})
- Throw an error, as per @code{scm-error} (@pxref{Error Reporting}).
- @end deftypefn
- @deftypefn {C Function} void scm_syserror (char *@var{subr})
- @deftypefnx {C Function} void scm_syserror_msg (char *@var{subr}, char *@var{message}, SCM @var{args})
- Throw an error with key @code{system-error} and supply @code{errno} in
- the @var{rest} argument. For @code{scm_syserror} the message is
- generated using @code{strerror}.
- Care should be taken that any code in between the failing operation
- and the call to these routines doesn't change @code{errno}.
- @end deftypefn
- @deftypefn {C Function} void scm_num_overflow (char *@var{subr})
- @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_misc_error (const char *@var{subr}, const char *@var{message}, SCM @var{args})
- Throw an error with the various keys described above.
- 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{Simple
- Output}), 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
- @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
- @c Local Variables:
- @c TeX-master: "guile.texi"
- @c End:
|