Defer in Racket
#lang racket
(require racket/file)
; Suppose we wanted to create a file, write to it,
; and then close when we're done. Here's how we could
; do that with dynamic-wind.
(define (main)
; dynamic-wind is used to ensure that the cleanup function
; (close-file) is called after the body (write-file) is executed,
; even if an exception occurs.
(let ([f (create-file "/tmp/defer.txt")])
(dynamic-wind
(lambda () (void)) ; setup (empty in this case)
(lambda () (write-file f))
(lambda () (close-file f)))))
(define (create-file p)
(displayln "creating")
(let ([out (open-output-file p #:exists 'replace)])
(if (output-port? out)
out
(error "Failed to create file"))))
(define (write-file f)
(displayln "writing")
(displayln "data" f))
; It's important to check for errors when closing a
; file, even in a cleanup function.
(define (close-file f)
(displayln "closing")
(with-handlers ([exn:fail? (lambda (e)
(fprintf (current-error-port)
"error: ~a~n"
(exn-message e))
(exit 1))])
(close-output-port f)))
(main)
In Racket, we don’t have a direct equivalent of Go’s defer
keyword. However, we can achieve similar functionality using the dynamic-wind
function. This function allows us to specify setup, body, and cleanup actions, ensuring that the cleanup is performed even if an exception occurs during the body execution.
Here’s a breakdown of the translation:
We define a
main
function that creates a file, writes to it, and ensures it’s closed afterwards.Instead of
defer
, we usedynamic-wind
. The first function (setup) is empty in this case. The second function (body) writes to the file. The third function (cleanup) closes the file.The
create-file
function opens a file for writing and returns the output port.The
write-file
function writes data to the file.The
close-file
function closes the file and handles any errors that might occur during closing.
To run the program:
$ racket defer.rkt
creating
writing
closing
This program demonstrates how to use dynamic-wind
in Racket to ensure that resources are properly cleaned up, similar to how defer
is used in other languages.