Next: iklib unwind-protect except 2, Previous: iklib unwind-protect dynamic, Up: iklib unwind-protect [Index]
A non–continuable exception is raised with raise, which can be
applied to any object; the argument to raise becomes the “raised
object”.  The purpose of raising a non–continuable exception is to
cause the application of a function, the current exception handler, to
the raised object; the exception handler is called in the dynamic
environment of the call to raise.
The execution flow is not meant return to the caller of
raise, so the exception handler has only two options:
(import (vicare))
(call/cc
    (lambda (escape)
      (with-exception-handler
          escape
        (lambda ()
          (raise 1)))))
⇒ 1
Reinstating a continuation to jump out of the exception handler is what
the standard guard syntax does when it handles an exception;
guard does more than this.
(import (vicare))
(call/cc
    (lambda (escape)
      (with-exception-handler
          escape
        (lambda ()
          (with-exception-handler
              (lambda (E)
                (raise E))
            (lambda ()
              (raise 1)))))))
⇒ 1
This is not the correct way of interfacing with the unwind–protection mechanism. In the following example we see that escaping from the exception handler skips the call to the ?unwind-handler.
(import (vicare)
  (only (vicare checks)
        with-result
        add-result))
(with-result
  (call/cc
      (lambda (escape)
        (with-exception-handler
            (lambda (E)
              (add-result 'exception-handler)
              (escape E))
          (lambda ()
            (with-unwind-protection
                (lambda (why)
                  (add-result 'cleanup))
              (lambda ()
                (add-result 'thunk-in)
                (raise 123)
                (add-result 'thunk-out))))))))
⇒ (123 (thunk-in exception-handler))
guardThis is the correct way of interfacing with the unwind–protection mechanism.
In the following example: the ?thunk raises a non–continuable
exception, which is catched by the else clause of a
guard use; this is equivalent to escaping from an exception
handler, but it does evaluate the ?unwind-handler.  We can see the
forms evaluation order.
#!vicare
(import (vicare)
  (only (vicare checks)
        with-result
        add-result))
(with-result
  (guard (E (else
             (add-result 'guard-else)
             E))
    (with-unwind-protection
        (lambda (why)
          (add-result 'cleanup))
      (lambda ()
        (add-result 'thunk-in)
        (raise 2)
        (add-result 'thunk-out)
        1))))
⇒ (2 (thunk-in cleanup guard-else))
In the following example: the ?thunk raises a non–continuable
exception, which is catched by the clause of a guard use; the
clause has test and expression.  We can see the forms evaluation order.
#!vicare
(import (vicare)
  (only (vicare checks)
        with-result
        add-result))
(with-result
  (guard (E ((begin
               (add-result 'guard-test)
               #t)
             (add-result 'guard-expr)
             E))
    (with-unwind-protection
        (lambda (why)
          (add-result 'cleanup))
      (lambda ()
        (add-result 'thunk-in)
        (raise 2)
        (add-result 'thunk-out)
        1))))
⇒ (2 (thunk-in guard-test cleanup guard-expr))
The following example with two nested guard uses and two nested
dynamic-wind calls, makes it even more clear the sequence of
forms evaluation.  The clause of the inner guard has test
expression returning #f, so the exception is re–raised with
raise-continuable.
#!vicare
(import (vicare)
  (only (vicare checks)
        with-result
        add-result))
(with-result
  (guard (E ((begin
               (add-result 'outer-guard-test)
               #t)
             (add-result 'outer-guard-expr)
             E))
    (guard (E ((begin
                 (add-result 'inner-guard-test)
                 #f)
               (add-result 'inner-guard-expr)
               E))
      (dynamic-wind
          (lambda ()
            (add-result 'outer-before))
          (lambda ()
            (with-unwind-protection
                (lambda (why)
                  (add-result 'cleanup))
              (lambda ()
                (dynamic-wind
                    (lambda ()
                      (add-result 'inner-before))
                    (lambda ()
                      (add-result 'thunk-in)
                      (raise 2)
                      (add-result 'thunk-out)
                      1)
                    (lambda ()
                      (add-result 'inner-after))))))
          (lambda ()
            (add-result 'outer-after))))))
⇒ (2 (outer-before inner-before thunk-in inner-after outer-after
       inner-guard-test
       outer-before inner-before inner-after outer-after
       outer-guard-test
       outer-before inner-before inner-after cleanup outer-after
       outer-guard-expr))
Let’s describe the sequence of operations:
outer-before inner-before thunk-inEverything goes fine until the ?thunk reaches thunk-in.
*The ?thunk raises an exception.  The exception handler of the
inner guard is applied to the raised object.
inner-after outer-afterThe continuation of the inner guard use is reinstated, the
dynamic extent of the call to ?thunk is exited: the dynamic
environment unwinds.
inner-guard-testThe clause test expression of the inner guard is evaluated in
the dynamic environment of the guard use: it returns #f.
outer-before inner-beforeThe continuation of the inner guard exception handler is
reinstated, the dynamic extent of the call to ?thunk is reentered:
the dynamic environment is restored.
*The exception is raised again by applying raise-continuable to
the same raised object.  The exception handler of the outer
guard is applied to the raised object.
inner-after outer-afterThe continuation of the outer guard use is reinstated, the
dynamic extent of the call to ?thunk is exited: the dynamic
environment unwinds.
outer-guard-testThe clause test expression of the outer guard is evaluated in
the dynamic environment of the outer guard: it returns #t.
outer-before inner-beforeThe continuation of the of the outer guard exception handler is
reinstated, the dynamic extent of the call to ?thunk is entered:
the dynamic environment is restored.
inner-after cleanup outer-afterThe continuation of the outer guard clause is reinstated, the
the dynamic extent of the call to ?thunk is exited: the dynamic
environment unwinds.  While unwinding: the ?thunk is found
terminated and the ?unwind-handler is called in the dynamic
environment of the with-unwind-protection use.
outer-guard-exprThe clause expression of the outer guard is evaluated in the
dynamic environment of the outer guard.
That’s Scheme!
Next: iklib unwind-protect except 2, Previous: iklib unwind-protect dynamic, Up: iklib unwind-protect [Index]