> Scheme already has a 'finally' in dynamic-wind.
Yup :-) I realised my mistake at about 3am on Sunday...
However I still think (finally) does something *slightly* different to
what is done by (dynamic-wind): where (dynamic-wind) executes its
third thunk on *any* throw past it, I'd expect (finally) to be
triggered by only either normal return, or exception-throw. That is,
the finally-clause gets installed *as an exception-handler*, not a
general unwinder. Perhaps (apologies for the untested, lowlevel
macro):
(define-macro (finally final-exp body . rest)
(let ((exn (gensym))
(result (gensym)))
`(with-exception-handler
(lambda (,exn)
,final-exp
(raise ,exn)) ; note[1]
(lambda ()
(let ((,result (begin
,body
,@rest)))
,final-exp
,result)))))
[1] I'm assuming here (I hope I read the SRFI correctly?) that (raise)
within an exception-handler chains to the next enclosing handler.
> (define-syntax finally
> (syntax-rules ()
> ((finally final-exp body . rest)
> (dynamic-wind (lambda () #f)
> (lambda () body . rest)
> (lambda () final-exp)))))
If someone is using call/cc to implement coroutines, or microthreads,
or what-have-you, this means that this
coroutine/thread/dynamic-context will give up its lock on each context
switch. What I was after was relinquishment of the lock when code
either returned normally, or threw an exception...
> The bottom line is that 'finally' is already there but it doesn't
> help as much as you would like.
Well, mostly because it's dynamic-wind, and dynamic-wind doesn't make
any distinctions between various kinds of throw.
Tony