Date: Sun, 1 Feb 2009 15:20:07 -0500 From: Taylor R Campbell campbell@mumble.net
(let ((new-foo ...) (old-foo #f)) (dynamic-wind (lambda () (set! old-foo foo) (set! foo new-foo)) thunk (lambda () (set! foo old-foo) (set! old-foo #f))))
Oops. This idiom is wrong, too. (It has the same issue as I described but for assignments that happen during the inner extent.) Here's what you really want, to dynamically bind FOO to <value> using DYNAMIC-WIND:
(let ((outer-foo #f) (inner-foo <value>)) (dynamic-wind (lambda () (let ((outer foo) (inner inner-foo)) (set! inner-foo #f) (set! foo inner) (set! outer-foo outer))) thunk (lambda () (let ((inner foo) (outer outer-foo)) (set! outer-foo #f) (set! foo outer) (set! inner-foo inner)))))
In MIT Scheme, where (SET! X Y) returns the old value of X, this is much more concisely written
(let ((outer-foo #f) (inner-foo <value>)) (dynamic-wind (lambda () (set! outer-foo (set! foo (set! inner-foo #f)))) thunk (lambda () (set! inner-foo (set! foo (set! outer-foo #f))))))