Days ago i started reading about continuations and delimited continuation control operators in Scheme (i’m working in racket but using scheme continuations). In that context i was trying the shift/reset operators implementation in terms of call/cc
according of this paper. The code works as expected:
(define-syntax reset
(syntax-rules ()
((reset ?e ...) (*reset (lambda () ?e ...)))))
(define-syntax shift
(syntax-rules ()
((shift ?k ?e ...) (*shift (lambda (?k) ?e ...)))))
(define-syntax abort
(syntax-rules ()
((abort ?e ...) (*abort (lambda () ?e ...)))))
(define (*abort _thunk)
((lambda (v) (*meta-continuation* v)) (_thunk)))
(define (*meta-continuation* v)
(error "You forgot the top-level reset..."))
(define (*abort _thunk)
((lambda (v) (*meta-continuation* v)) (_thunk))) ;; <- the line i'm asking for
(define (*reset thunk)
(let ((mc *meta-continuation*))
(call-with-current-continuation2
(lambda (k)
(set! *meta-continuation*
(lambda (v)
(set! *meta-continuation* mc)
(k v)))
(abort (thunk))))))
(define (*shift f)
(call-with-current-continuation2
(lambda (k) (abort (f (lambda (v) (reset (k v))))))))
;; PROGRAM STARTS HERE
(+ 1 (reset (* 2 (shift k (k (k 4)))))) ; should be 17
First, macros for reset, shift and abort are defined with simply wraps the arguments in lambdas, then the proper *abort, *reset and *shift functions are defined.
however i had bad times trying to understand the *abort
function definition.
In particular, if i try to replace the code
((lambda (v) (*meta-continuation* v)) (_thunk)))
or this equivalent version in the paper that also works (let ((v (_thunk))) (*meta-continuation* v))
with a direct call :
(*meta-continuation* (_thunk))
the program no longer gives the correct result of 17
but 9
instead (as if the stored continuations in reset from nested shifts were discarded).
That is, I tend to think that binding the result of the call to _thunk (_thunk)
to a variable v
and then calling (*meta-continuation* v)
should be the same as the call (*meta-continuation* (_thunk))
. Even if (_thunk)
or (*meta-continuation* ...)
does not return because call/cc.
Is not in both cases (*meta_continuation* [])
the continuation of (_thunk)
?
What am I not understanding here?
Thanks.