Tuesday, December 20, 2005

Try-catch-finally in Scheme

I need a little break from all this parsing crap. Let's have some macro fun. Here's a PLT Scheme version of Java's try-catch-finally. Note the use of symbolic literals, rather than the usual syntax-rules/syntax-case literals list. This is due to my philosophy on macro keywords.
(define-for-syntax (symbolic-identifier=? id1 id2)
(eq? (syntax-object->datum id1)
(syntax-object->datum id2)))

(define-syntax (try stx)
(syntax-case* stx (catch finally) symbolic-identifier=?
[(_ e (catch ([pred handler] ...)) (finally e0 e1 ...))
#'(dynamic-wind void
(lambda ()
(with-handlers ([pred handler] ...)
e))
(lambda () e0 e1 ...))]
[(_ e (catch ([pred handler] ...)))
#'(with-handlers ([pred handler] ...) e)]
[(_ e (finally e0 e1 ...))
#'(dynamic-wind void
(lambda () e)
(lambda () e0 e1 ...))]))
Example use:
(try (begin (printf "hi")
(printf " there")
(printf ", world")
(newline)
(error 'blah))
(catch ([exn? (lambda (exn) 3)]))
(finally (printf "finally!~n")))

1 comment:

Yin-So Chen said...

Hi -

this is cool. Thanks!

I have tested the code and was wondering about the order of execution. It seems that it is ordered as:

1) try
2) finally
3) catch

AFAIK Java and other try/catch/finally generally have the order of

1) try
2) catch
3) finally

Is there a reason that the catch block (i.e. with-handlers) is executed last?

Thanks,