<stephan@pcrm.win.tue.nl> wrote:
+---------------
| Indeed, if you wants to mix both uses of call/cc, you soon
| find out that this means that you cannot use dynamic-wind
| for try..finally purposes.
+---------------
You can't anyway, since you'd want the unwinding to *stop* when it hits
the "after" clause that was being used for the "finally" part. That is,
consider this naive/obvious implementation of CL's "unwind-protect",
which assumes that all system errors invoke a continuation captured
in the top-level REPL (which is the case in many implementations):
> (defmacro unwind-protect (protected-form . cleanup-forms)
`(begin
(call/cc
(lambda (break)
(dynamic-wind
(lambda () #t)
(lambda () ,protected-form)
(lambda () (break)))))
,@cleanup-forms))
> (unwind-protect (/ 1 0)
(print "This prints anyway")
17)
/: division by zero
This prints anyway
17
>
However, R5RS clearly says:
The effect of using a captured continuation to enter or exit
the dynamic extent of a call to "before" or "after" is undefined.
So you can't legally do that [even though it works in the particular
implementation I tried it in].
I ran into exactly this problem when implementing a private REPL inside
a script that was supposed to be portable between MzScheme and SCM. SCM
did what I had hoped for, but MzScheme barfed on a continuation being
invoked in the "after" thunk -- it called the "after" thunk again!!
[Hey, "undefined" behavior can be *anything*, right?] Thankfully, the
Rice guys fixed the problem in the next release.
+---------------
| (Since Scheme isn't clairvoyant and cannot guess in which of
| the two meanings you want to use call/cc.)
| Which means that you probably end up:
| 1. not using the real dynamic-wind
| 2. write your own call-with-winding-continuation + fake-dynamic-wind
| 3. do exceptions with the new call/wc and use the original call/cc
| for threading
+---------------
It's worse than that. The Scheme spec makes no guarantee that program
errors will invoke a [captured top-level] continuation, thus you have
no guarantee whatsoever that, say, "(/ 1 0)" or "(* 5 'foo)" will even
*do* an unwind!!
-Rob
p.s. Precisely because MzScheme *was* designed (or evolved) to support
instructional programming, with DrScheme (and its MrEd-based GUIs) allowing
execution of arbitrary student code yet wanting to catch all errors itself,
MzScheme exception-handling system *does* interact fairly nicely with both
call/cc & dynamic-wind. But that's just one implementation, not the standard.
-----
Rob Warnock, 31-2-510 rpw3@sgi.com
Network Engineering http://reality.sgi.com/rpw3/
Silicon Graphics, Inc. Phone: 650-933-1673
1600 Amphitheatre Pkwy. PP-ASEL-IA
Mountain View, CA 94043