GNU bug report logs - #18356
Should partial continuations capture the dynamic environment?

Previous Next

Package: guile;

Reported by: Taylan Ulrich Bayirli/Kammer <taylanbayirli <at> gmail.com>

Date: Fri, 29 Aug 2014 18:13:02 UTC

Severity: normal

Tags: notabug

Done: Mark H Weaver <mhw <at> netris.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 18356 in the body.
You can then email your comments to 18356 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-guile <at> gnu.org:
bug#18356; Package guile. (Fri, 29 Aug 2014 18:13:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Taylan Ulrich Bayirli/Kammer <taylanbayirli <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-guile <at> gnu.org. (Fri, 29 Aug 2014 18:13:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Taylan Ulrich Bayirli/Kammer <taylanbayirli <at> gmail.com>
To: bug-guile <at> gnu.org
Subject: Should partial continuations capture the dynamic environment?
Date: Fri, 29 Aug 2014 20:12:09 +0200
On Guile 2.0.11:

scheme@(guile-user)> (define (capture-dynenv)
                       (let ((tag (make-prompt-tag "dynenv-capture")))
                         (call-with-prompt
                          tag
                          (lambda ()
                            ((abort-to-prompt tag)))
                          (lambda (call-in-captured-dynenv)
                            (lambda (proc)
                              (call-in-captured-dynenv proc))))))
scheme@(guile-user)> (define param (make-parameter 0))
scheme@(guile-user)> (define dynenv (parameterize ((param 1))
                                      (capture-dynenv)))
scheme@(guile-user)> (parameterize ((param 2))
                       (dynenv (lambda () (param))))
$9 = 2

In other words, when a partial continuation is called, the dynamic
environment at that call-time is in effect for the continuation, and
not the one from when the continuation was captured.

Is this behavior correct and what I'm trying to do won't work, or
should the code return 1 as I had expected?


For comparison, the following variant that uses call/cc works fine:

(define (capture-dynenv)
  ((call/cc
    (lambda (call-in-captured-dynenv)
      (lambda ()
        (lambda (proc)
          (call/cc
           (lambda (go-back)
             (call-in-captured-dynenv
              (lambda ()
                (call-with-values proc go-back)))))))))))

Taylan




Information forwarded to bug-guile <at> gnu.org:
bug#18356; Package guile. (Fri, 29 Aug 2014 18:27:01 GMT) Full text and rfc822 format available.

Message #8 received at 18356 <at> debbugs.gnu.org (full text, mbox):

From: Taylan Ulrich Bayirli/Kammer <taylanbayirli <at> gmail.com>
To: 18356 <at> debbugs.gnu.org
Subject: Should partial continuations capture the dynamic environment?
Date: Fri, 29 Aug 2014 20:26:47 +0200
Some more examples; this one works fine:

scheme@(guile-user)> (define (with-captured-dynenv proc)
                       (let ((tag (make-prompt-tag "dynenv-capture")))
                         (call-with-prompt
                          tag
                          (lambda ()
                            (proc (lambda (thunk)
                                    (abort-to-prompt tag thunk))))
                          (lambda (return thunk)
                            (return (thunk))))))
scheme@(guile-user)> (define param (make-parameter 0))
scheme@(guile-user)> (parameterize ((param 1))
                       (with-captured-dynenv
                        (lambda (dynenv)
                          (parameterize ((param 2))
                            (dynenv (lambda () (param)))))))
$2 = 1

But not this simpler one:

scheme@(guile-user)> (define (with-captured-dynenv proc)
                       (let ((tag (make-prompt-tag "dynenv-capture")))
                         (call-with-prompt
                          tag
                          (lambda ()
                            ((abort-to-prompt tag)))
                          (lambda (call-in-captured-dynenv)
                            (proc call-in-captured-dynenv)))))
scheme@(guile-user)> (parameterize ((param 1))
                       (with-captured-dynenv
                        (lambda (dynenv)
                          (parameterize ((param 2))
                            (dynenv (lambda () (param)))))))
$3 = 2

Taylan




Information forwarded to bug-guile <at> gnu.org:
bug#18356; Package guile. (Tue, 14 Oct 2014 14:26:02 GMT) Full text and rfc822 format available.

Message #11 received at 18356 <at> debbugs.gnu.org (full text, mbox):

From: Taylan Ulrich Bayirli/Kammer <taylanbayirli <at> gmail.com>
To: 18356 <at> debbugs.gnu.org
Subject: Should partial continuations capture the dynamic environment?
Date: Tue, 14 Oct 2014 16:25:27 +0200
It has been explained on the #guile Freenode channel that this
behavior is indeed desired and not a bug, being argued for by some
authors of papers on delimited continuations:

http://www.cs.utah.edu/plt/publications/icfp07-fyff.pdf

http://okmij.org/ftp/papers/DDBinding.pdf


In short, no: partial continuations in Guile should not (and do not)
capture their dynamic environment.


Thanks to Andy Wingo for the clarification.

Taylan




Information forwarded to bug-guile <at> gnu.org:
bug#18356; Package guile. (Tue, 14 Oct 2014 16:50:01 GMT) Full text and rfc822 format available.

Message #14 received at 18356 <at> debbugs.gnu.org (full text, mbox):

From: Nala Ginrut <nalaginrut <at> gmail.com>
To: "Taylan Ulrich Bayirli/Kammer" <taylanbayirli <at> gmail.com>
Cc: 18356 <at> debbugs.gnu.org
Subject: Re: bug#18356: Should partial continuations capture the dynamic
 environment?
Date: Wed, 15 Oct 2014 00:48:59 +0800
Thanks for researching and explaining this issue!
It's helpful for me to think about how to deal with my async server
design based on delimited-continuation.
I think it's fine if it doesn't capture dynamic environment, even
cooler, so that the dynamic state could be well understood and traced
by users more easily.


On Tue, Oct 14, 2014 at 10:25 PM, Taylan Ulrich Bayirli/Kammer
<taylanbayirli <at> gmail.com> wrote:
> It has been explained on the #guile Freenode channel that this
> behavior is indeed desired and not a bug, being argued for by some
> authors of papers on delimited continuations:
>
> http://www.cs.utah.edu/plt/publications/icfp07-fyff.pdf
>
> http://okmij.org/ftp/papers/DDBinding.pdf
>
>
> In short, no: partial continuations in Guile should not (and do not)
> capture their dynamic environment.
>
>
> Thanks to Andy Wingo for the clarification.
>
> Taylan
>
>
>




Information forwarded to bug-guile <at> gnu.org:
bug#18356; Package guile. (Wed, 15 Oct 2014 16:39:03 GMT) Full text and rfc822 format available.

Message #17 received at 18356 <at> debbugs.gnu.org (full text, mbox):

From: Mark H Weaver <mhw <at> netris.org>
To: Taylan Ulrich Bayirli/Kammer <taylanbayirli <at> gmail.com>
Cc: 18356 <at> debbugs.gnu.org, Nala Ginrut <nalaginrut <at> gmail.com>,
 request <at> debbugs.gnu.org
Subject: Re: bug#18356: Should partial continuations capture the dynamic
 environment?
Date: Wed, 15 Oct 2014 12:37:28 -0400
tags 18356 + notabug
close 18356
thanks

Taylan Ulrich Bayirli/Kammer <taylanbayirli <at> gmail.com> writes:
> In short, no: partial continuations in Guile should not (and do not)
> capture their dynamic environment.

I think this requires further explanation, because the above statement
is not quite correct.

Partial continuations do not capture the _entire_ dynamic environment,
but they *do* capture (and later restore) the _part_ of the dynamic
environment that was established between the prompt and abort.

Thinking in terms of 'dynamic-wind', 'abort-to-prompt' unwinds from the
abort to the prompt, and when the partial continuation is later invoked,
it will rewind from the prompt back to the abort before resuming the
computation.

Thinking in terms of dynamic environments, 'abort-to-prompt' captures
the dynamic bindings that were established between the prompt and abort,
and these captured bindings are composed on top of the dynamic
environment of the call site when the partial continuation is later
invoked.

So, for example:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> (call-with-prompt
                      'foo
                      (lambda ()
                        (dynamic-wind
                          (lambda () (display "entering\n"))
                          (lambda () (abort-to-prompt 'foo))
                          (lambda () (display "leaving\n"))))
                      (lambda (k) k))
entering
leaving
$1 = #<partial-continuation 10934680>
scheme@(guile-user)> ($1 'hello)
entering
leaving
$2 = hello
--8<---------------cut here---------------end--------------->8---

Above, the 'dynamic-wind' between the prompt and abort is rewound when
invoking the partial continuation.

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> (dynamic-wind
                       (lambda () (display "entering\n"))
                       (lambda ()
                         (call-with-prompt
                          'foo
                          (lambda () (abort-to-prompt 'foo))
                          (lambda (k) k)))
                       (lambda () (display "leaving\n")))
entering
leaving
$3 = #<partial-continuation 10972810>
scheme@(guile-user)> ($3 'hello)
$4 = hello
--8<---------------cut here---------------end--------------->8---

Above, the 'dynamic-wind' outside of the prompt is _not_ rewound when
invoking the partial continuation.

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> (define my-param (make-parameter #f))
scheme@(guile-user)> (call-with-prompt
                      'foo
                      (lambda ()
                        (parameterize ((my-param 5))
                          ((abort-to-prompt 'foo))))
                      (lambda (k) k))
$5 = #<partial-continuation 109f9c60>
scheme@(guile-user)> ($5 my-param)
$6 = 5
--8<---------------cut here---------------end--------------->8---

Above, the dynamic binding of 'my-param' to 5 is restored when invoking
the partial continuation, because it was established between the prompt
and abort.

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> (parameterize ((my-param 5))
                       (call-with-prompt
                        'foo
                        (lambda () ((abort-to-prompt 'foo)))
                        (lambda (k) k)))
$7 = #<partial-continuation 107a37a0>
scheme@(guile-user)> ($7 my-param)
$8 = #f
--8<---------------cut here---------------end--------------->8---

Above, the dynamic-binding of 'my-param' to 5 is _not_ restored, because
it was established outside of the prompt.

      Mark




Added tag(s) notabug. Request was from Mark H Weaver <mhw <at> netris.org> to control <at> debbugs.gnu.org. (Wed, 15 Oct 2014 16:39:05 GMT) Full text and rfc822 format available.

bug closed, send any further explanations to 18356 <at> debbugs.gnu.org and Taylan Ulrich Bayirli/Kammer <taylanbayirli <at> gmail.com> Request was from Mark H Weaver <mhw <at> netris.org> to control <at> debbugs.gnu.org. (Wed, 15 Oct 2014 16:39:05 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Thu, 13 Nov 2014 12:24:05 GMT) Full text and rfc822 format available.

This bug report was last modified 9 years and 172 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.