I am not sure I understand the difference between the delimited continuation operator pairs prompt/control
and reset/shift
. I understand some basic examples of use, but in those examples their behavior is the same.
I have found this example in "On the Dynamic Extent of Delimited Continuations", by Dariusz Biernacki and Olivier Danvy:
reset
(fn () => shift (fn k => 10 + (k 100))
+ shift (fn k’ => 1))
prompt
(fn () => control (fn k => 10 + (k 100))
+ control (fn k’ => 1))
which I have translated into Scheme and ran successfully with the expected results in Racket using the racket/control
library:
(reset (+ (shift k (+ 10 (k 100)))
(shift kk 1)))
;; ==> 11
(prompt (+ (control k (+ 10 (k 100)))
(control kk 1)))
;; ==> 1
Their explanation is that,
In the first case, when
k
is applied, the expressionshift (fn kk => 1)
is evaluated in a context that could be represented functionally asfn v => 100 + v
and in a meta-context that could be represented as(fn v => 10 + v) :: nil
; this context is captured and discarded and the intermediate answer is1
; this intermediate answer is plugged into the top context from the meta-context, i.e.,fn v => 10 + v
is applied to1
; the next intermediate answer is11
; and it is the final answer since the meta-context is empty.In the second case, when
k
is applied, the expression control(fn kk => 1)
is evaluated in a context that results from composingfn v => 10 + v
andfn v => 100 + v
(and therefore could be represented functionally asfn v => 10 + (100 + v)
), and in a meta-context which is empty; this context is captured and discarded and the intermediate answer is1
; and it is the final answer since the meta-context is empty.
I was confused by the "meta-context" idea, which they define as
Intuitively, an evaluation context represents the rest of the computation up to the
nearest enclosing delimiter, and a meta-context represents all of the remaining computation.
I didn't get the idea of "all of the remaining computation" here, I'm not sure
why it would be (fn v => 10 + v) :: nil
in the first example (why exactly that piece of code?)
I was wondering if there is any more examples, possible with more details, of the differences between those two pairs of operators, possibly without too much use of formal semantics, which is a really above my head.
edit: I also see that the order of the two shift
-surrounded expressions does make a difference: if I swap them, then the result is 1
for both control
and reset
.