|20-CS-4003-001||Organization of Programming Languages||Fall 2018|
Visit all values of a list
(define call/cc call-with-current-continuation) (define amb-fail '()) (define amb (lambda () (call/cc (lambda (sk) (call/cc (lambda (fk1) (set! amb-fail (lambda () (fk1 'fail))) (sk 1))) (call/cc (lambda (fk2) (set! amb-fail (lambda () (fk2 'fail))) (sk 2))) (call/cc (lambda (fk3) (set! amb-fail (lambda () (fk3 'fail))) (sk 3))))))) (define back (lambda () (amb-fail)))
>> (define a (amb)) >> a ;Value: 1 >> (back) >> a ;Value: 2 >> (back) >> a ;Value: 3When (amb) is invoked continuations sk and fk1 are picked up (note: invoking sk effects a return from the outer call/cc and invoking fk1 effects a return from the first inner call/cc). Then, in the first inner call/cc, amb-fail is changed to invoke fk1 and finally, sk is invoked to effect a return from the outer call/cc with value 1 which is given to a.
Invoking (back) invokes amb-fail which invokes fk1 and effects a return from the 1st inner call/cc with value 'fail (which is not used, by the way). Control proceeds to the next expression in sequence which is the second inner call/cc. In that call/cc expression continuation fk2 is grabbed (when invoked it will return a value to the 2nd inner call/cc) then amb-fail is set to invoke fk2 when it is called. Finally sk is invoked returning value 2 to a.
This repeats until 'fail is returned by the last inner call/cc expression and consequently the outer call/cc expression.