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