[racket] Continuation marks

From: Gustavo Massaccesi (gustavo at oma.org.ar)
Date: Sat Sep 6 19:31:57 EDT 2014

Thanks to everyone. It's much clearer now.

I tried to get the same output anyway. This is the closest I could
get. The example involves a little of "cheating", because the add-cm-x
function actually never return in the traditional sense, but it use
call/cc and abort/cc to get the same effect.

Perhaps this can be "improved" with more work, but it was only a
curiosity question to understand more about the continuation marks.

;--
#lang racket/base
(define (display-cm-x)
  (display
   (continuation-mark-set->list
    (current-continuation-marks) 'x))
  (display "  first: ")
  (displayln
   (continuation-mark-set-first
    (current-continuation-marks) 'x)))

(define prompt (make-continuation-prompt-tag 'temp))

(define (add-cm-x v)
  (call-with-composable-continuation
   (lambda (xx)
     (with-cm-x 7
       (let ([r (xx (void))])
         (abort-current-continuation prompt r))))))

(define-syntax-rule (with-cm-x v body ...)
  (with-continuation-mark 'x v
    body ...))

(call-with-continuation-prompt
 (lambda ()
   (with-cm-x 0
     (let ()
       (display-cm-x) ;==>(0) first: 0
       (with-cm-x 7
         (display-cm-x)) ;==>(7 0) first: 7
       (display-cm-x) ;==>(0) first: 0
       (add-cm-x 7)
       (display "!")
       (display-cm-x) ;==>(0 7 0) first: 0 :(
       333)))
 prompt
 (lambda (x) x))

(newline)

(call-with-continuation-prompt
 (lambda ()
   (let ()
     (display-cm-x) ;==>() first: #f
     (with-cm-x 7
       (display-cm-x)) ;==>(7) first: 7
     (display-cm-x) ;==>() first: #f
     (add-cm-x 7)
     (display "!")
     (display-cm-x) ;==>(7) first: 7 :)
     333))
 prompt
 (lambda (x) x))

;--

Gustavo

On Sat, Sep 6, 2014 at 1:19 PM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> The 'preserves-marks flag makes sense only in the context of the JIT's
> implementation.
>
> At the Racket level, there's no way to write a function `f` so that
>
>  (with-continuation-mark
>   'x
>   'my-value
>   (begin
>    (f)
>    (continuation-mark-set-first #f 'x)))
>
> produces anything other than 'my-value. Even if `f` contains a
> `with-continuation-mark` form to set a mark with the key 'x, returning
> from `f` necessarily means leaving the dynamic extent of that form, so
> the mark will not be visible.
>
> It turns out that the JITted form of `with-continuation-mark` is not
> responsible for popping a mark stack as it returns. Instead, every
> non-tail position is wrapped with a kind of push and pop of the
> continuation-mark stack. Since `(f)` appears in a non-tail position
> within with `begin` form, the call with be wrapped.
>
> If `f` is known to not have a `with-continuation-mark` as a tail form,
> however, then the push and pop of the continuation-mark stack will not
> be necessary around the `(f)` call. The 'preserves-marks flag tells the
> JIT that it can make that assumption. (In retrospect, a better name
> would be 'has-no-wcm-in-tail-position.)
>
>
> At Sat, 6 Sep 2014 11:36:37 -0300, Gustavo Massaccesi wrote:
>> I agree that to get this output, using continuation marks is a bad
>> idea. It'd be much better to use a parameter (or set!ing a global
>> variable at a last resort).
>>
>> I'm trying to understand continuations marks. I'm reading some parts
>> of the Racket compiler, and internally the functions have some flags
>> that are not visible from the Racket code.
>>
>> One of the flags is 'preserves-marks. From
>> http://docs.racket-lang.org/raco/decompile.html
>>
>> > The preserves-marks? field is true if calling the function is expected to
>> leave continuation marks unchanged by the time it returns.
>>
>> So: Can a function change the continuation marks after it returns?
>> What does that exactly mean? Can I use that to complete the code in my
>> original e-mail? Is that a good idea for a real program?
>>
>> (The last question is easy: No. :) )
>>
>>
>> I also read the answer from Matthias Felleisen. I'm not sure that I
>> understood it completely, but somehow it give me a new idea to solve
>> this. But I need to try it before I'm sure it works.
>>
>>
>> Gustavo
>>
>> On Fri, Sep 5, 2014 at 7:04 PM, John Clements <clements at brinckerhoff.org> wrote:
>> >
>> > On Sep 5, 2014, at 2:24 PM, Gustavo Massaccesi <gustavo at oma.org.ar> wrote:
>> >
>> >> I'm trying to add a continuation mark inside a function, but I want
>> >> that the new mark to be visible after the functions returns. (Mostly
>> >> for curiosity, not an actual problem.)
>> >>
>> >> I want something like this:
>> >>
>> >> ;--
>> >> #lang racket/base
>> >>
>> >> (define (display-cm-x)
>> >>  (displayln
>> >>   (continuation-mark-set->list
>> >>    (current-continuation-marks) 'x)))
>> >>
>> >> (define (add-cm-x v)
>> >>  '???)
>> >>
>> >> (define-syntax-rule (with-cm-x v body ...)
>> >>  (with-continuation-mark 'x v
>> >>    body ...))
>> >>
>> >> (let ()
>> >>  (display-cm-x) ;==>()
>> >>  (with-cm-x 7
>> >>    (display-cm-x)) ;==>(7)
>> >>  (display-cm-x) ;==>()
>> >>  (add-cm-x 7)
>> >>  (display-cm-x) ;actual==>(), expected==>(7)
>> >>  )
>> >> ;--
>> >>
>> >> The last line prints (), but I wish it prints (7).
>> >
>> > This is going to sound flip, but … it sounds like you don’t want continuation
>> marks. The whole point of continuation marks is that they’re associated with
>> continuations, and will disappear when those continuations are gone.
>> >
>> > The example you give isn’t quite enough to figure out exactly what you want;
>> it sounds like some combination of fluid-let and … something else.
>> >
>> > Maybe you can describe why it is that you want this behavior?
>> >
>> > John
>> >
>>
>> ____________________
>>   Racket Users list:
>>   http://lists.racket-lang.org/users


Posted on the users mailing list.