[racket] Continuation marks
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