[plt-scheme] Re: "unwind-protect" for PLT Scheme?
I've found this documents which could be of interest:
Dorai Sitaram. "Unwind-protect in portable Scheme". Scheme Workshop
2003. November 2003:
http://repository.readscheme.org/ftp/papers/sw2003/Unwind.pdf
Here is a critique from Kent Pitman about the lack of a proper
"unwind-protect" in Scheme:
http://www.nhplace.com/kent/PFAQ/unwind-protect-vs-continuations-update-2003.html
2009/7/5 Eli Barzilay <eli at barzilay.org>:
> On Jul 4, Shriram Krishnamurthi wrote:
>> You only need the before-thunk argument to do something if you have
>> continuations somewhere deep within the body expression. (But note
>> that even if you don't use continuations, you just might use a
>> library function that does.) As long as neither you nor a library
>> does, you can pass something trivial as before-thunk, such as void.
>> That reduces to being the same as Lisp's unwind-protect.
>
> Sorry to add another post on this, but I'll try to make a quick
> summary of this whole thing in plain English (as much as I can call
> what *I* write "plain English"):
>
> * When no continuations are involved, `dynamic-wind' is perfectly fine
> as is, and you can set up the resource either in the before thunk,
> or before the whole call:
>
> (let ([foo (open-output-file ...)])
> (dynamic-wind void
> (lambda () ...do stuff with foo...)
> (lambda () ...close foo...)))
>
> or
>
> (let ([foo #f])
> (dynamic-wind (lambda () (set! foo (open-output-file ...)))
> (lambda () ...do stuff with foo...)
> (lambda () ...close foo...)))
>
> * When continuations are involved, then control can jump into or out
> of the main thunk, and you have several options to choose from.
> Here the before thunk becomes important since it can be called not
> just once, but several times -- once when it starts, and a pair of
> after-before calls for each jump out of and back into the main
> thunk.
>
> Just ignoring this makes it possible for your code to run into
> problems that are similar in nature to writing code that is not
> thread-safe: in both cases the problem is not in your own code, but
> in the way it is being called or in the way library calls it
> performs behave. And this analogy carries over to how people deal
> with it: lots of user code just ignores the whole issue, but you
> need to be more careful if you're writing some library, or parts of
> the core language. [`call/cc' is notorious in exposing all kinds of
> things about how things are implemented (for example, IIRC there was
> a point in the (distant?) past where you could squeeze two different
> behaviors out of mzscheme's `map' function because the
> implementation was optimizing uses with a few functions).]
>
> * Options for dealing with this are:
>
> - Ignore the whole thing, and use the first form above.
>
> - Arrange for the resource to be properly opened and closed on the
> before/after thunks -- which means that you need to make sure
> that, for example, you open the file in `append' mode so when
> jumping out and back in the resource will be recreated. Of
> course, this depends on the code doing something simple, like just
> writing to the file.
>
> - Forbid re-entry: you make a before thunk that remembers if it was
> already called -- if that's the case, then you know that somehow
> control went out and back in, and you make it throw an appropriate
> error. This can be convenient if, for example, it is meaningless
> to use the resource after it was already released.
>
> - Intentionally avoid creating and releasing the resource in a
> `dynamic-wind', so it will only be released when control leaves
> normally. An example for this would be:
>
> (let ([foo (open-output-file ...)])
> (begin0 (...do stuff with foo...)
> (...close foo...)))
>
> or better:
>
> (let ([foo (open-output-file ...)])
> (define (close-foo) ...close foo...)
> (with-handlers ([(lambda (x) #t)
> (lambda (e) (close-foo) (raise e))])
> (begin0 (...do stuff with foo...)
> (close-foo))))
>
> This works if when control happens to go out, it will also go back
> in, so eventually control leaves as usual.
>
> - There's a number of variants on these and subtle points involved
> etc.
>
> --
> ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
> http://barzilay.org/ Maze is Life!
>