Today my goal is to learn about how to use continuations to implement a few of the following things in Racket:
dynamic-wind
- Exceptions (including
define-syntax
) - Coroutines
- Time-traveling search
- Generators
- Threads
- Non-deterministic programming
dynamic-wind
dynamic-wind
is a function which takes three arguments: pre-thunk
, value-thunk
, and post-thunk
. It has the special property that even if value-thunk
returns early (from calling a continuation for example) post-thunk
will still be called.
It can be used to implement cleanup, such as closing a file, no matter what happens in value-thunk
. A great use case for dynamic-wind
is using the post-thunk
for cleanup code like closing a file once you’re done reading from it:
(define (safe-read-file input-file)
(let ([p (open-input-file input-file)])
(dynamic-wind
(lambda () '())
(lambda () '()) ; do something with the file here
(lambda ()
(begin
(close-input-port p)))))) ; this will always be called!
Exceptions
After reading through Matt Might’s article on implementing exceptions, I realized that I had to take a slight detour to study the define-syntax
procedure, which is a form of macro in Scheme.
define-syntax
define-syntax
is how you define macros, or templates of code, which expand into more code! I don’t really fully understand this very well, but I hope to dive into this a bit more tomorrow.
Questions
I ended up not getting very far with learning how to implement exceptions in Racket (I had lots of chats with great people!) so here are some open questions I hope to answer tomorrow:
- How does
define-syntax
work? What aresyntax-rules
? I think I’ll read over this post and macros in the Racket guide - How do I display a fully-expanded macro for debugging?
- How can I write a
try/catch
macro usingdefine-syntax
? - How can I use continuations to implement coroutines?