[racket] Delimited continuations and parameters

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon May 14 21:00:49 EDT 2012

See the docs for `parameterize':

 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.

where "parameterization" is hyperlinked to

 In a non-empty continuation, a parameter’s value is determined through
 a parameterization that is associated with the nearest enclosing
 continuation frame though a continuation mark (whose key is not
 directly accessible). A parameterization maps each parameter to a
 preserved thread cell, and the combination of thread cell and current
 thread yields the parameter’s value. A parameter procedure sets or
 accesses the relevant thread cell for its parameter.

In other words, every `parameterize' uses the same continuation mark,
so that `(parameterize ([r 10]) ...)' associates the parameterization
continuation mark with a single record that maps `r' to 10, `p' to 1,
etc. The entire record is carried by the delimited continuation.

In the ICFP'07 paper on delimited continuations in Racket, we wrote (at
the end of section 5) that we'd probably change `parameterize', but
we've never gotten around to that change. Meanwhile, raw continuation
marks (as modeled directly in that paper) essentially match the
dynamic-binding form of Kiselyov et al.

At Mon, 14 May 2012 19:26:39 -0400, Asumu Takikawa wrote:
> Hi all,
> Here is a code snippet that uses both delimited continuations and
> parameters (translated from the paper "Delimited Dynamic Binding"[1]):
>   #lang racket
>   (require racket/control)
>   (define p (make-parameter 0))
>   (define r (make-parameter 0))
>   ((λ (f)
>      (parameterize ([p 2])
>        (parameterize ([r 20])
>          (f 0))))
>    (parameterize ([p 1])
>      (reset
>        (parameterize ([r 10])
>          ((λ (x) (+ (p) (r)))
>           (shift f f))))))
> If you run this, it produces 11. The authors of [1] argue that it should
> return 12, namely because it follows the principle that "the dynamic
> bindings in scope are those in the context".
> That makes some sense, considering that when you eventually get to the
> call (f 0) in the first lambda, your context looks like
>   (parameterize ([p 2])
>     (parameterize ([r 20])
>       (f 0)))
>   where f = (λ (y)
>               (parameterize ([r 10])
>                 ((λ (x) (+ (p) (r)))
>                  y)))
> according to shift/reset semantics. From this context, p = 2, r = 10
> could make sense.
> That said, I don't really have an intuition for what semantics for
> dynamic binding & delimited control is useful. Is there a pragmatic
> reason for why Racket's parameters and delimited control interact in
> this fashion?
> [1]: http://okmij.org/ftp/Computation/dynamic-binding.html#DDBinding
> Cheers,
> Asumu
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users

Posted on the users mailing list.