Re: [racket-users] fcontrol and dynamic-wind
> On Nov 30, 2019, at 20:52, Matthew Flatt wrote: > > They are, as long as any invoked `dynamic-wind` thunks are safe in > atomic mode. (After all, `unsafe-abort-current-continuation/no-wind` > and `unsafe-call-with-composable-continuation/no-wind` were created to > support `unsafe/try-atomic`.) Alright, thanks, that does make sense. I think it’s still probably not the right solution, since the idea is that effect handlers ought to be implementable in user code, and I wouldn’t want to ask users to regularly interact with atomic mode. Maybe it can play a role in a safe abstraction, though. Also, I realized shortly after I wrote my last email that I actually did see an effect system paper a while back that addressed these issues: “Algebraic Effect Handlers with Resources and Deep Finalization” by Daan Leijen. Looking at it again, it even cites Sitaram’s “Unwind-protect in portable Scheme” article I mentioned earlier! I may have forgotten about it because it appears to have only ever been released as a Microsoft Research technical report, not published at any academic conference. In any case, I didn’t really understand it when I first saw it, so I need to reread it more carefully, but an initial skim seems promising. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/E6F8DAA0-8CF6-4745-B071-AAC1BFB3D880%40gmail.com.
Re: [racket-users] fcontrol and dynamic-wind
At Sat, 30 Nov 2019 20:38:26 -0600, Alexis King wrote: > I’m not even sure if continuation operations are safe > in atomic mode. They are, as long as any invoked `dynamic-wind` thunks are safe in atomic mode. (After all, `unsafe-abort-current-continuation/no-wind` and `unsafe-call-with-composable-continuation/no-wind` were created to support `unsafe/try-atomic`.) -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/5de32ae4.1c69fb81.30ea6.bc95SMTPIN_ADDED_MISSING%40gmr-mx.google.com.
Re: [racket-users] fcontrol and dynamic-wind
> On Nov 30, 2019, at 09:23, Matthew Flatt wrote: > > There's not a safe way. In many cases, Racket lets you write new things > that have the power of built-in through unsafe APIs --- and it turns > out that there are unadvertised procedures (provided by the primitive > `#%unsafe` module) for this particular case: > > unsafe-abort-current-continuation/no-wind > unsafe-call-with-composable-continuation/no-wind Thanks, those operations look helpful. I do worry a little bit that maybe they only solve the `dynamic-wind` problem, though, and don’t solve some other, related problems. For example, imagine I were to replace `dynamic-wind` with `parameterize-break`: (run-amb/first (thunk (parameterize-break #f (+ (amb 1 2) (amb 3 4) Presumably, breaks would still be re-enabled and local exception handlers would be uninstalled during the handling of `amb`, even with the use of those unsafe operations, right? That seems wrong, too, since presumably the client would be surprised if a break were delivered inside the scope of `(parameterize-break #f _)`. I think what it comes down to is I somehow want the ability to “atomically” insert some new continuation frames around the current prompt without uninstalling the current break state, exception handlers, continuation marks, and so on. I want to be able to go from E_1[(run-amb/first E_2[(amb e_1 e_2)])] to E_1[(run-amb/first (or E_2[e_1] E_2[e_2]))] in a single “step.” I guess I could resort to atomic mode, but that seems like a very heavy hammer, and I’m not even sure if continuation operations are safe in atomic mode. On the other hand, I don’t really know what a safe API for what I’m trying to do would look like. > I don't know of any published work on this topic (so let me know if you > find something!). As you probably have seen already, our ICFP'07 paper > just points out that `dynamic-wind` causes problems, but doesn't try to > hold `dynamic-wind` itself responsible for those problems. > > An opinion and some pointers to newsgroup discussions: > > http://okmij.org/ftp/continuations/against-callcc.html#dynamic_wind > > It would be interesting to check whether `dynamic-wind` is really > needed in Racket libraries, at least in its current form. Most uses are > really a "finally" mechanism that could be tied to explicit escapes > like exceptions, instead of imposed for all continuation jumps. Maybe > the uses that don't fit that pattern would be better expressed with > another mechanism. Maybe the guarantees on `dynamic-wind` just need to > be weakened and the `/no-wind` variants declared "safe" by defining > away the unsafety. Yes, most of the relevant discussions I’ve found have been about Lisp’s `unwind-protect` and how it relates to Scheme’s `dynamic-wind`. It’s alluded to in Matthias’s original POPL ’88 paper and mentioned explicitly in the following LASC paper, but neither address this particular issue. I also found Dorai Sitaram’s “Unwind-protect in portable Scheme”[1] and the related commentary by Kent Pitman[2] and Will Clinger[3], but though obviously related, both Sitaram and Clinger seem to imagine a system where the author of the program defines all control operations, so there isn’t as much of a problem. I’ve also been trying to find if any of these issues are discussed in any algebraic effects literature, but I haven’t found anything there yet, either. [1]: http://www.ccs.neu.edu/~dorai/uwcallcc/uwcallcc.html [2]: http://www.nhplace.com/kent/PFAQ/unwind-protect-vs-continuations-overview.html [3]: http://www.ccs.neu.edu/home/will/UWESC/uwesc.sch -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/AE70AFAC-89FA-4260-A8AE-6726A1AFE261%40gmail.com.
Re: [racket-users] fcontrol and dynamic-wind
You're trying to implement `amb` where a client can mix `amb` and `dynamic-wind` and get sensible behavior, right? The `dynamic-wind` operation certainly interferes with building new control forms. Racket threads and other control forms that need to interact a certain way with `dynamic-wind` end up being built in at the same level as `dynamic-wind`. At Sat, 30 Nov 2019 06:15:16 -0600, Alexis King wrote: > Is there any way to do that with Racket’s continuation machinery, There's not a safe way. In many cases, Racket lets you write new things that have the power of built-in through unsafe APIs --- and it turns out that there are unadvertised procedures (provided by the primitive `#%unsafe` module) for this particular case: unsafe-abort-current-continuation/no-wind unsafe-call-with-composable-continuation/no-wind These are currently used to implement `ffi/unsafe/try-atomic`. Using the `/no-wind` operations will make `amb` interact with `dynamic-wind` in the way you have in mind, I think. At Sat, 30 Nov 2019 06:15:16 -0600, Alexis King wrote: > Also, is this kind of thing discussed anywhere in the literature? I don't know of any published work on this topic (so let me know if you find something!). As you probably have seen already, our ICFP'07 paper just points out that `dynamic-wind` causes problems, but doesn't try to hold `dynamic-wind` itself responsible for those problems. An opinion and some pointers to newsgroup discussions: http://okmij.org/ftp/continuations/against-callcc.html#dynamic_wind It would be interesting to check whether `dynamic-wind` is really needed in Racket libraries, at least in its current form. Most uses are really a "finally" mechanism that could be tied to explicit escapes like exceptions, instead of imposed for all continuation jumps. Maybe the uses that don't fit that pattern would be better expressed with another mechanism. Maybe the guarantees on `dynamic-wind` just need to be weakened and the `/no-wind` variants declared "safe" by defining away the unsafety. Matthew -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/5de2897c.1c69fb81.1d190.4683SMTPIN_ADDED_MISSING%40gmr-mx.google.com.
[racket-users] fcontrol and dynamic-wind
Hello, I have been playing with implementing algebraic effects using delimited control, and Dorai Sitaram’s `fcontrol` and `%` operators are a natural fit. For example, it’s straightforward to implement McCarthy’s `amb` operator using them: (define amb-tag (make-continuation-prompt-tag 'amb)) ; -> none/c (define (fail) (fcontrol 'fail #:tag amb-tag)) ; -> boolean? (define (choice) (fcontrol 'choice #:tag amb-tag)) (define-syntax amb (syntax-rules () [(_) (fail)] [(_ e)e] [(_ e0 e ...) (if (choice) e0 (amb e ...))])) The whole point of algebraic effect handlers is that we can interpret the same effect multiple ways, and `%` makes that easy. For example, we can write one `amb` handler that returns only the first result and another one that returns all results: (define (run-amb/first proc) (% (proc) (λ (op k) (match op ['fail #f] ['choice (or (run-amb/first (thunk (k #t))) (run-amb/first (thunk (k #f])) #:tag amb-tag)) (define (run-amb/all proc) (let go ([proc (thunk (list (proc)))]) (% (proc) (λ (op k) (match op ['fail '()] ['choice (append (go (thunk (k #t))) (go (thunk (k #f])) #:tag amb-tag))) This mostly works nicely, but the way it interacts with `dynamic-wind` leaves something to be desired: > (run-amb/first (thunk (dynamic-wind (thunk (displayln "--> in")) (thunk (+ (amb 1 2) (amb 3 4))) (thunk (displayln "<-- out") --> in <-- out --> in <-- out --> in <-- out 4 This is a little bit silly, since control is jumping out of the extent of `dynamic-wind` only to immediately re-enter it. If `dynamic-wind` is being used to guard access to a lock or pooled resource, we probably don’t want it to be released and reacquired on every call to `amb`. However, I’m not sure how I can rearrange things to make that possible. I can’t just store the current `amb` handler in a parameter/continuation mark because it really does need to extend the continuation of the whole computation. Is there any way to do that with Racket’s continuation machinery, or would I need to use mutable state to imperatively extend a list of continuations maintained by the current handler? Also, is this kind of thing discussed anywhere in the literature? Thanks, Alexis -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/9EEF26EF-C60C-49B7-92D4-27648C111213%40gmail.com.