dynamic-wind

dynamic-wind is how parameterize, with-exception-handler, and port-closing helpers stay correct in the presence of call/cc. Re-entering a continuation runs BEFORE again.

;; (dynamic-wind before thunk after): BEFORE runs whenever control enters THUNK's dynamic extent,
;; AFTER runs whenever control leaves it, including via continuations and exceptions.
(dynamic-wind
  (lambda () (display "[enter]"))
  (lambda () (display "body") 'result)
  (lambda () (display "[exit]")))          ; prints [enter]body[exit], returns result

;; Leaving via a continuation still runs AFTER
(call/cc
  (lambda (k)
    (dynamic-wind
      (lambda () (display "acquire "))
      (lambda () (k 'escaped) (display "never printed"))
      (lambda () (display "release ")))))  ; prints "acquire release ", returns escaped

;; Resource management helper
(define (call-with-resource open close proc)
  (let ((r #f))
    (dynamic-wind
      (lambda () (set! r (open)))
      (lambda () (proc r))
      (lambda () (close r) (set! r #f)))))