0

I'm trying to build a good intuition behind continuations in Racket, I want to write a function that suspend it's execution and returns a continuation that when called continue the work from where it was suspended.

I kind of achieved this with this code

# lang racket

(define resume-with null) ;; called to resume a call of suspend
(define (suspend abort)
  (call/cc (lambda (k)
             (set! resume-with k)
             (abort))))



(define (foo) ;; a function that do suspended work
  (call/cc (lambda (abort)
             ;; abort is used to abort from foo from within suspend
             ;; if we do not abort the whole body will be executed
             (printf "-> A\n")
             (define x (suspend abort))
             (printf "-> B\n")
             (define y (suspend abort))
             (printf "-> C\n")
             (+ x y))))

But in this example I save the continuation in resume-with I want to return it instead.

I was trying something like this

(define (foo1)
  (call/cc (lambda (abort)
             (define x (call/cc (lambda (k)
                                  (abort k))))
             (printf "x -> ~a\n" x)
             (+ x 1))))

I would like to achieve the smaller and simpler example in a single function, using only call/cc and no mutability.

This example kind of works, but it seems that the final result is not usable in another computation, I don't understand what's happening

foo.rkt> (define k (foo1)) ;; I call it and save the continuation, so far so good
foo.rkt> k ;; the continuation is a procedure
#<procedure>
foo.rkt> (k 1) ;; I call the continuation, the print shows up so we seem to be in good shape, but
x -> 1
foo.rkt> (+ 1 (k 1)) ;; if I try to apply this inside another computation I get this weird error, the 2 in the error message suggests is some what computed the `(+ x 1)` but the rest of the error I don't know how to interpret 
; application: not a procedure;
;  expected a procedure that can be applied to arguments
;   given: 2
geckos
  • 5,687
  • 1
  • 41
  • 53

2 Answers2

0

Okay I find out after trying another example, I don't fully understand why but the value of k becomes the 2 after the first call

foo.rkt> (define k (foo2))
foo.rkt> (k 1)
x -> 1
foo.rkt> k
2
foo.rkt> (+ 1 k)
3
foo.rkt> 
geckos
  • 5,687
  • 1
  • 41
  • 53
0

You have suspended the computation inside the definition - it is "waiting" for the value of x.
(The initial "value" of k is not the value returned from (foo1) but the continuation you called k in (define x ....)

Illustration:

(define (foo1)
  (call/cc (lambda (abort)
             (define x {this is where the continuation returns})
             (+ x 1))))

When you do (k 1), the definition continues with x bound to 1, then it prints the output, and lastly binds the value of (+ x 1) to k.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82