[plt-scheme] finally

From: Doug Orleans (dougo at place.org)
Date: Wed Dec 21 14:37:26 EST 2005

Eli Barzilay writes:
 > If you're already going down to the `with-handlers' level, why not
 > just use it for the finally clause?  Something like:
 >   (define-syntax try
 >     (syntax-rules (finally)
 >       ((_ expr catch-clause ... (finally finally-expr ...))
 >        (let ([finalizer (lambda () finally-expr ...)])
 >          (with-handlers ((exn? (lambda (exn) (finalizer) catch-expr ...))
 >                          ...
 >                          (void (lambda (e) (finalizer) (raise e))))
 >            (begin0 expr (finalizer)))))))
 > (which is a bit different than your version.)

Yes, it's a bit different from the Java semantics as well:


 * The finally-exprs should be evaluated at the end of each
   catch-clause, not the beginning.
 * If there's an exception during any catch clause, the finally-exprs
   should still be evaluated.

But I think you're right, with-handlers is better than using
dynamic-wind, because it will only catch exceptions and not other
transfers of control.  For example, if the try expression is opening a
port, you want to close the port if the expression completes normally
or if there's an exception, but if it jumps to another continuation
and then jumps back you want to leave it open.

  (define-syntax try
    (syntax-rules (finally)
      ((_ expr catch-clause ... (finally finally-expr ...))
       (let ((finalizer (lambda () finally-expr ...)))
	 (with-handlers ((void (lambda (exn) (finalizer) (raise exn))))
	   (begin0 (try expr catch-clause ...) (finalizer)))))
      ((_ expr ((exn? exn) catch-expr ...) ...)
       (with-handlers ((exn? (lambda (exn) catch-expr ...))

Hm, what about escape continuations?  It would be reasonable to close
the port in this case, since control will never come back.  Is there a
way for dynamic-wind (or something else) to differentiate between
escape continuations and full continuations?

--dougo at place.org

Posted on the users mailing list.