1
votes

I am new to Scheme programming and have been trying to understand the control flow of the programs having call-with-current-continuation in them. To be more specific, I want to know when the call to any continuation is invoked where is the control transferred and what happens after that. It would be really helpful if the below mentioned program is considered for the explanation.

(define call/cc call-with-current-continuation)

(define amb-exit '())

(define amb
 (lambda ()
    (call/cc
      (lambda (m)
       (call/cc
         (lambda (f1)
           (set! amb-exit (lambda () (f1 'exit)))
           (m 1)))
       (call/cc
         (lambda (f2)
           (set! amb-exit (lambda () (f2 'exit)))
           (m 2)))
       (call/cc
         (lambda (f3)
           (set! amb-exit (lambda () (f3 'exit)))
           (m 3)))))))

(define back (lambda () (amb-exit)))

Now, I try to run the code this way (define a (amb)) and then I get the value in the terminal like this ;Value: a. Then in the terminal I check the value of a which returns me ;Value: 1. Then I call (back) I get a with the new value ;Value: 2. So on...

I know that when I do (define a (amb) the continuation f1 is invoked in the statement (set! amb-exit (lambda () (f1 'exit))) which transfers the control back to the first inner call/cc and the f1 continuation returns exit.

The thing that I am not able to understand is why the ;Value: a is ;Value: 1 instead of the value exit which is returned by f1? The moment this part (f1 'exit) is executed, control returns back to first inner call/cc abandoning whatever (in this case (m 1)) after it. So, this part (m 1) should never be invoked because the first inner continuation i.e. f1 is returned with exit even before hitting (m 1).

Any helpful comments regarding call-with-current-continuation in Scheme would also be appreciated.

Note: Using MIT/GNU Scheme

1
I've explained call/cc a couple of times, but I believe this is the simplest. It takes a while to understand call/cc and it really helps to implement a basic scheme compiler. - Sylwester

1 Answers

1
votes

No, when you do (define a (amb)) the continuation f1 is not invoked, because it is behind (i.e. inside) a lambda.

No, (set! amb-exit (lambda () (f1 'exit))) sets amb-exit to the lambda function, and then the control passes to (m 1) which does invoke the continuation m. Which returns 1 from (amb) in (define a (amb)), which thus sets a to 1.

When you later call (back) it calls (amb-exit) which at that point invokes the f1 continuation with (f1 'exit) which returns the value 'exit from the (call/cc (lambda (f1) ...)) form. This value is discarded, and control passes into the (call/cc (lambda (f2) ...)) form, with similar effects.