DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 

(guile.info.gz) Lazy Catch

Info Catalog (guile.info.gz) Throw (guile.info.gz) Exceptions (guile.info.gz) Exception Implementation
 
 26.7.4 Catch Without Unwinding
 ------------------------------
 
 A "lazy catch" is used in the same way as a normal `catch', with KEY,
 THUNK and HANDLER arguments specifying the exception type, normal case
 code and handler procedure, but differs in one important respect: the
 handler procedure is executed without unwinding the call stack from the
 context of the `throw' expression that caused the handler to be invoked.
 
  -- Scheme Procedure: lazy-catch key thunk handler
  -- C Function: scm_lazy_catch (key, thunk, handler)
      This behaves exactly like `catch', except that it does not unwind
      the stack before invoking HANDLER.  The HANDLER procedure is not
      allowed to return: it must throw to another catch, or otherwise
      exit non-locally.
 
    Typically, HANDLER should save any desired state associated with the
 stack at the point where the corresponding `throw' occurred, and then
 throw an exception itself -- usually the same exception as the one it
 caught.  If HANDLER is invoked and does _not_ throw an exception, Guile
 itself throws an exception with key `misc-error'.
 
    Not unwinding the stack means that throwing an exception that is
 caught by a `lazy-catch' is _almost_ equivalent to calling the
 `lazy-catch''s handler inline instead of each `throw', and then
 omitting the surrounding `lazy-catch'.  In other words,
 
      (lazy-catch 'key
        (lambda () ... (throw 'key args ...) ...)
        handler)
 
 is _almost_ equivalent to
 
      ((lambda () ... (handler 'key args ...) ...))
 
 But why only _almost_?  The difference is that with `lazy-catch' (as
 with normal `catch'), the dynamic context is unwound back to just
 outside the `lazy-catch' expression before invoking the handler.  (For
 an introduction to what is meant by dynamic context,  Dynamic
 Wind.)
 
    Then, when the handler _itself_ throws an exception, that exception
 must be caught by some kind of `catch' (including perhaps another
 `lazy-catch') higher up the call stack.
 
    The dynamic context also includes `with-fluids' blocks (REFFIXME),
 so the effect of unwinding the dynamic context can also be seen in fluid
 variable values.  This is illustrated by the following code, in which
 the normal case thunk uses `with-fluids' to temporarily change the
 value of a fluid:
 
      (define f (make-fluid))
      (fluid-set! f "top level value")
 
      (define (handler . args)
        (cons (fluid-ref f) args))
 
      (lazy-catch 'foo
                  (lambda ()
                    (with-fluids ((f "local value"))
                      (throw 'foo)))
                  handler)
      =>
      ("top level value" foo)
 
      ((lambda ()
         (with-fluids ((f "local value"))
           (handler 'foo))))
      =>
      ("local value" foo)
 
 In the `lazy-catch' version, the unwinding of dynamic context restores
 `f' to its value outside the `with-fluids' block before the handler is
 invoked, so the handler's `(fluid-ref f)' returns the external value.
 
    `lazy-catch' is useful because it permits the implementation of
 debuggers and other reflective programming tools that need to access the
 state of the call stack at the exact point where an exception or an
 error is thrown.  For an example of this, see REFFIXME:stack-catch.
 
Info Catalog (guile.info.gz) Throw (guile.info.gz) Exceptions (guile.info.gz) Exception Implementation
automatically generated byinfo2html