You're right.  Racket also gives a:1 b:1 c:1.

So in Racket, a new parameterization is made during the dynamic extent of
reset, other parameterizations is also kept.  But if no new
parameterization occurs, the parameterization at the moment of reset is not
kept.

In srfi-226 ref impl, reset (or call-with-continuation-prompt) always keeps
the parameterization.

I wonder how other implementations behave.

To me, the Racket model seems fragile.  Usually whether parameterization
occurs during a dynamic extent is out of control of the programmer who uses
reset.







On Fri, Nov 18, 2022 at 9:07 PM Marc Nieper-Wißkirchen <
marc.nie...@gmail.com> wrote:

> Am Sa., 19. Nov. 2022 um 08:04 Uhr schrieb Shiro Kawai <
> shiro.ka...@gmail.com>:
> >
> > Yup, that nested parameterize example gives different results.
> >  Racket, Gauche-release: a:1 b:1 c:2
> >  Srfi-226 ref.impl. , Gauche-HEAD: a:1 b:1 c:1
>
> Can you recheck? The nested parameterize (with the N parameterization
> inside reset) gives a:1 b:1 c:1 on Racket 8.2 here.
>
> >
> > The Racket model is explainable with dynamic-wind setting/resetting
> dynamic values of specified parameters (and that's how Gauche-release
> handles them).
> >
> > I feel srfi-226 ref impl model is easier to understand (just assuming a
> continuation prompt remembers all the dynamic state).  However, we don't
> want the behavior of two implementation strategies to differ.
> >
> > Furthermore, this means that any dynamic state that is managed either by
> dynamic-wind or by continuations marks, depending on implementations, can
> behave differently, doesn't it?
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > On Fri, Nov 18, 2022 at 8:47 PM Marc Nieper-Wißkirchen <
> marc.nie...@gmail.com> wrote:
> >>
> >> Am Sa., 19. Nov. 2022 um 01:04 Uhr schrieb Shiro Kawai <
> shiro.ka...@gmail.com>:
> >> >
> >> > I'm inclined to the reference implementation behavior; the last
> example you show seems very confusing, especially that the dynamic value of
> m retrieved in seemingly the same dynamic environment (on the prompt) is
> affected by the parameterization of unrelated parameters.  In general you
> wound't know what reparameterization is done during the inner calls.
> >> >
> >> > On the other hand, the behavior of Racket (and the current version of
> Gauche) can be explained with dynamic-wind.
> >> >
> >> > ```
> >> > (define c #f)
> >> >
> >> > (define (foo)
> >> >   (dynamic-wind
> >> >     (lambda () (print 'pre1))
> >> >     (lambda ()
> >> >       (reset
> >> >        (print 'pre2)
> >> >        (shift k (print 'cont) (set! c k))
> >> >        (print 'post2)))
> >> >     (lambda () (print 'post1))))
> >> >
> >> > (define (bar)
> >> >   (dynamic-wind
> >> >     (lambda () (print 'pre3))
> >> >     (lambda () (c #f))
> >> >     (lambda () (print 'post3))))
> >> > ```
> >> >
> >> > All implementations (Racket, srfi-226 reference impl, Gauche release,
> Gauche HEAD) agree that what handlers are called:
> >> >
> >> > > (foo)
> >> > pre1
> >> > pre2
> >> > cont
> >> > post1
> >> >
> >> > > (bar)
> >> > pre3
> >> > post2
> >> > post3
> >> >
> >> > If parameterization is implemented by dynamic-wind, the invocation of
> the delimited continuation won't restore dynamic values of parameters when
> reset is called (which would've been done by pre1).
> >>
> >> Compare this to my example with the nested parameterization where the
> >> dynamic value of the outer parameter was also restored.  To make this
> >> explainable with dynamic-wind, setting one parameter through
> >> dynamic-wind would have to set all parameters:
> >>
> >> This here prints a:1 b:1 c:1:
> >>
> >> (define (print . xs) (for-each display xs) (newline))
> >>
> >> (define m (make-parameter 0))
> >> (define n (make-parameter 0))
> >>
> >> (define c #f)
> >>
> >> (define (foo)
> >>   (parameterize ((m 1))
> >>     (reset
> >>      (parameterize ((n 1))
> >>        (print 'a: (m))
> >>        (shift k (print 'b: (m)) (set! c k))
> >>        (print 'c: (m))))))
> >>
> >> (define (bar)
> >>   (parameterize ((m 2))
> >>     (c #f)))
> >>
> >> (foo)
> >> (bar)
> >>
> >> >
> >> >
> >> >
> >> >
> >> >
> >> > On Fri, Nov 18, 2022 at 11:28 AM Marc Nieper-Wißkirchen <
> marc.nie...@gmail.com> wrote:
> >> >>
> >> >> Am Fr., 18. Nov. 2022 um 22:12 Uhr schrieb Marc Nieper-Wißkirchen
> >> >> <marc.nie...@gmail.com>:
> >> >> >
> >> >> > At first sight, Racket's behavior looks strange (tested with 8.2):
> >> >> >
> >> >> > This expression
> >> >> >
> >> >> > (let ((m (make-parameter 0))
> >> >> >       (n (make-parameter 0)))
> >> >> >   (define k
> >> >> >     (parameterize ((m 1))
> >> >> >       (call-with-continuation-prompt
> >> >> >        (lambda ()
> >> >> >          (parameterize ()
> >> >> >            ((call-with-composable-continuation
> >> >> >              (lambda (k)
> >> >> >                (lambda () k)))))))))
> >> >> >   (k (lambda () (values (m) (n)))))
> >> >> >
> >> >> > evaluates to the values 0 0.  The following expression, however,
> >> >> >
> >> >> > (let ((m (make-parameter 0))
> >> >> >       (n (make-parameter 0)))
> >> >> >   (define k
> >> >> >     (parameterize ((m 1))
> >> >> >       (call-with-continuation-prompt
> >> >> >        (lambda ()
> >> >> >          (parameterize ((n 1))
> >> >> >            ((call-with-composable-continuation
> >> >> >              (lambda (k)
> >> >> >                (lambda () k)))))))))
> >> >> >   (k (lambda () (values (m) (n)))))
> >> >> >
> >> >> > evaluates to the values 1 1.
> >> >> >
> >> >> > The only difference is that the inner parameterization is not
> trivial.
> >> >> >
> >> >> > It seems to be that each non-trivial parameterize installs a new
> >> >> > continuation mark (holding the complete new parameterization).
> This
> >> >> > is captured by c-w-c-c.  However, when there is no non-trivial
> >> >> > parameterize, no continuation mark about parameterizations is
> >> >> > installed in the frames that are captured, and so reinstalling the
> >> >> > delimited continuation does not restore the relevant continuation
> >> >> > marks.
> >> >> >
> >> >> > Actually, this model happens to coincide with my wording in SRFI
> 226:
> >> >> > "Conceptually, each continuation contains at least one otherwise
> >> >> > inaccessible parameterization continuation mark, whose value is a
> >> >> > parameterization. The parameterization of a continuation is the
> value
> >> >> > of the most recent parameterization continuation mark in the
> >> >> > continuation. The parameterization of the current continuation is
> the
> >> >> > current parameterization. The (current) parameterization can
> >> >> > conceptually be seen as part of the dynamic environment."
> >> >> >
> >> >> > If I take this seriously, my sample implementation has to be
> corrected.
> >> >>
> >> >> PS I would like to hear some opinions about it.  I think the sample
> >> >> implementation's behavior (namely, to record the current
> >> >> parameterization and the current exception handler stack at each
> >> >> prompt so that it will be captured) makes more sense than what I
> wrote
> >> >> literally (and what is Racket's behavior).
> >> >>
> >> >> >
> >> >> > Am Fr., 18. Nov. 2022 um 20:57 Uhr schrieb Marc Nieper-Wißkirchen
> >> >> > <marc.nie...@gmail.com>:
> >> >> > >
> >> >> > > Here is an example using only the primitives:
> >> >> > >
> >> >> > > (let ((m (make-parameter 0)))
> >> >> > >   ((parameterize ((m 4))
> >> >> > >      (call-with-continuation-prompt
> >> >> > >       (lambda ()
> >> >> > >         ((call-with-composable-continuation
> >> >> > >           (lambda (k)
> >> >> > >             (abort-current-continuation
> (default-continuation-prompt-tag)
> >> >> > >               (lambda () k))))))))
> >> >> > >    m))
> >> >> > >
> >> >> > > In Racket, it evaluates to 0 and not to 4.
> >> >> > >
> >> >> > > Am Fr., 18. Nov. 2022 um 20:51 Uhr schrieb Shiro Kawai <
> shiro.ka...@gmail.com>:
> >> >> > > >
> >> >> > > > Racket v8.6 behaves the same way.
> >> >> > > >
> >> >> > > > On Fri, Nov 18, 2022 at 9:29 AM Shiro Kawai <
> shiro.ka...@gmail.com> wrote:
> >> >> > > >>
> >> >> > > >> I used Racket v7.2, and here's the full transcription.  I'm
> going to check with the newest Racket.
> >> >> > > >>
> >> >> > > >> shiro@scherzo:~/src/srfi-226$ racket
> >> >> > > >> Welcome to Racket v7.2.
> >> >> > > >> > (require racket/control)
> >> >> > > >> > (define (print . xs) (for-each display xs) (newline))
> >> >> > > >> > (define m (make-parameter 0))
> >> >> > > >> > (define c #f)
> >> >> > > >> > (define (foo)
> >> >> > > >>     (parameterize ((m 1))
> >> >> > > >>       (reset
> >> >> > > >>        (print 'a: (m))
> >> >> > > >>        (shift k (print 'b: (m)) (set! c k))
> >> >> > > >>        (print 'c: (m)))))
> >> >> > > >> > (define (bar)
> >> >> > > >>     (parameterize ((m 2))
> >> >> > > >>       (c #f)))
> >> >> > > >> > (foo)
> >> >> > > >> a:1
> >> >> > > >> b:1
> >> >> > > >> > (bar)
> >> >> > > >> c:2
> >> >> > > >>
> >> >> > > >>
> >> >> > > >> On Fri, Nov 18, 2022 at 9:26 AM Marc Nieper-Wißkirchen <
> marc.nie...@gmail.com> wrote:
> >> >> > > >>>
> >> >> > > >>> Thanks for the report, Shiro!
> >> >> > > >>>
> >> >> > > >>> I have to investigate Racket's behavior.  In 11.3.2 of the
> Racket
> >> >> > > >>> reference, it says: "If a continuation is captured during the
> >> >> > > >>> evaluation of parameterize, invoking the continuation
> effectively
> >> >> > > >>> re-introduces the parameterization, since a parameterization
> is
> >> >> > > >>> associated to a continuation via a continuation mark (see
> Continuation
> >> >> > > >>> Marks) using a private key."  This seems to be consistent
> with SRFI
> >> >> > > >>> 226 and its sample implementation, but not consistent with
> your Racket
> >> >> > > >>> experiments.
> >> >> > > >>>
> >> >> > > >>> Am Fr., 18. Nov. 2022 um 20:07 Uhr schrieb Shiro Kawai <
> shiro.ka...@gmail.com>:
> >> >> > > >>> >
> >> >> > > >>> > It seems that there's a disagreement in how a delimited
> continuation captures dynamic environment, between Racket and srfi-226.
> >> >> > > >>> >
> >> >> > > >>> > Suppose the following code:
> >> >> > > >>> >
> >> >> > > >>> > ```
> >> >> > > >>> > (define (print . xs) (for-each display xs) (newline))
> >> >> > > >>> >
> >> >> > > >>> > (define m (make-parameter 0))
> >> >> > > >>> >
> >> >> > > >>> > (define c #f)
> >> >> > > >>> >
> >> >> > > >>> > (define (foo)
> >> >> > > >>> >   (parameterize ((m 1))
> >> >> > > >>> >     (reset
> >> >> > > >>> >      (print 'a: (m))
> >> >> > > >>> >      (shift k (print 'b: (m)) (set! c k))
> >> >> > > >>> >      (print 'c: (m)))))
> >> >> > > >>> >
> >> >> > > >>> > (define (bar)
> >> >> > > >>> >   (parameterize ((m 2))
> >> >> > > >>> >     (c #f)))
> >> >> > > >>> > ```
> >> >> > > >>> >
> >> >> > > >>> > With srfi-226 (using reset/shift as given in the srfi)
> reference implementation on Chez, I get this:
> >> >> > > >>> >
> >> >> > > >>> > ```
> >> >> > > >>> > > (run foo)
> >> >> > > >>> > a:1
> >> >> > > >>> > b:1
> >> >> > > >>> > > (run bar)
> >> >> > > >>> > c:1
> >> >> > > >>> > ```
> >> >> > > >>> >
> >> >> > > >>> > With Racket racket/control, I get this:
> >> >> > > >>> >
> >> >> > > >>> > ```
> >> >> > > >>> > > (foo)
> >> >> > > >>> > a:1
> >> >> > > >>> > b:1
> >> >> > > >>> > > (bar)
> >> >> > > >>> > c:2
> >> >> > > >>> > ```
> >> >> > > >>> >
> >> >> > > >>> > I'm switching Gauche's internals to srfi-226 based model,
> and I noticed the difference---the current released version of Gauche
> (relying on dynamic-wind to handle parameterization) works like Racket,
> while the srfi-226 based version (using dynamic env chain to keep
> parameters) works like srfi-226 reference implementation.
> >> >> > > >>> >
> >> >> > > >>> > I think srfi-226 behavior is more consistent (when the
> delimited continuation is invoked, it restores the dynamic environment of
> the continuation of reset), but is there a plausible explanation of Racket
> behavior?
> >> >> > > >>> >
> >> >> > > >>> > This difference actually caused a compatibility problem of
> an existing application so I want to understand it fully.
> >> >> > > >>> >
> >> >> > > >>> >
> >> >> > > >>> >
> >> >> > > >>> >
> >> >> > > >>> >
> >> >> > > >>> >
> >> >> > > >>> >
>

Reply via email to