Previous: , Up: iklib unwind-protect   [Index]


6.9.13 Unwinding call/cc

We have seen that performing a raw escape from an exception handler skips calling the unwind handlers installed in the body:

(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 2))
          (lambda ()
            (with-unwind-handler
                (lambda (why)
                  (add-result 'unwind-handler))
              (lambda ()
                (add-result 'body-in)
                (raise 1))))))))
⇒ (2 (body-in exception-handler))

this problem can be solved by using unwinding-call/cc rather than the standard call/cc.

Function: unwinding-call/cc receiver

Similar to call/cc, but calling the escape procedure causes the invocation of the unwind handlers installed in the dynamic environment up until the saved continuation is restored.

There are limitations:

NOTE After some development iterations, the implementation of this primitive has taken a shape quite similar to the function call/cc-escaping proposed by Will Clinger in http://www.ccs.neu.edu/home/will/UWESC/uwesc.sch.

Usage examples:

(import (vicare)
  (only (vicare checks)
        with-result
        add-result))

(with-result
  (unwinding-call/cc
      (lambda (escape)
        (with-unwind-handler
            (lambda (why)
              (add-result 'unwind-handler))
          (lambda ()
            (add-result 'body-in)
            (escape 1))))))
⇒ (1 (body-in unwind-handler))

(with-result
  (unwinding-call/cc
      (lambda (escape)
        (with-exception-handler
            (lambda (E)
              (add-result 'exception-handler)
              (escape 2))
          (lambda ()
            (with-unwind-handler
                (lambda (why)
                  (add-result 'unwind-handler))
              (lambda ()
                (add-result 'body-in)
                (raise 1))))))))
⇒ (2 (body-in exception-handler unwind-handler))

;;Calling unwinding escape procedure from outside the
;;dynamic extent of the call to the receiver.
;;
(let ((escape-proc #f))
  (unwinding-call/cc
      (lambda (escape)
        (set! escape-proc escape)))
  (escape-proc))
error→ &non-reinstatable

;;Calling unwinding escape procedure twice.
;;
(let ((again-proc #f))
  (unwinding-call/cc
      (lambda (escape)
        (call/cc
            (lambda (again)
              (set! again-proc again)))
        (escape)))
  (again-proc))
error→ &non-reinstatable

Previous: , Up: iklib unwind-protect   [Index]