Call-with-current-continuation - Examples

Examples

As shown by the following example, call/cc can be used to emulate the functionality of the return statement known from C-style languages, which is missing from Scheme:

(define (f return) (return 2) 3) (display (f (lambda (x) x))) ; displays 3 (display (call-with-current-continuation f)) ; displays 2

Calling f with a regular function argument first applies this function to the value 2, then returns 3. However, when f is passed to call/cc (as in the last line of the example), applying the parameter (the continuation) to 2 forces execution of the program to jump to the point where call/cc was called, and causes call/cc to return the value 2. This is then printed by the display function.

In the following example, call/cc is used twice: once to generate a "return" continuation as in the first example and once to suspend an iteration through a list of items:

;; -> ( -> X u 'you-fell-off-the-end) (define (generate-one-element-at-a-time lst) ;; Hand the next item from a-list to "return" or an end-of-list marker (define (control-state return) (for-each (lambda (element) (set! return (call-with-current-continuation (lambda (resume-here) ;; Grab the current continuation (set! control-state resume-here) (return element))))) lst) (return 'you-fell-off-the-end)) ;; (-> X u 'you-fell-off-the-end) ;; This is the actual generator, producing one item from a-list at a time (define (generator) (call-with-current-continuation control-state)) ;; Return the generator generator) (define generate-digit (generate-one-element-at-a-time '(0 1 2))) (generate-digit) ;; 0 (generate-digit) ;; 1 (generate-digit) ;; 2 (generate-digit) ;; you-fell-off-the-end

Every time the loop is about to process another item from the list, the function grabs the current continuation, and assigns it to the variable 'control-state'. This variable initially is the closure that iterates through all elements of the list. As the computation progresses, it becomes a closure that iterates through a suffix of the given list. While the use of "call/cc" is unnecessary for a linear collection, such as , the code generalizes to any collection that can be traversed.

Call-with-current-continuation can also express other sophisticated primitives. For example, the following code performs cooperative multitasking using continuations:

;; Cooperative multitasking using call-with-current-continuation ;; in 25 lines of scheme ;; The list of threads waiting to run. This is a list of one ;; argument non-returning functions (continuations, mostly) ;; A continuation is a non-returning function, just like (exit), ;; in that it never gives up control to whoever called it. (define readyList ') ;; A non-returning function. If there is any other thread ;; waiting to be run, it causes the next thread to run if there ;; is any left to run, otherwise it calls the original exit ;; which exits the whole environment. (define exit ;; The original exit which we override. (let ((exit exit)) ;; The overriding function. (lambda (if (not (null? readyList)) ;; There is another thread waiting to be run. ;; So we run it. (let ((cont (car readyList))) (set! readyList (cdr readyList)) ;; Since the readyList is only non-returning ;; functions, this will not return. (cont ')) ;; Nothing left to run. ;; The original (exit) is a non returning function, ;; so this is a non-returning function. (exit))))) ;; Takes a one argument function with a given ;; argument and forks it off. The forked function's new ;; thread will exit if/when the function ever exits. (define (fork fn arg) (set! readyList (append readyList ;; This function added to the ;; readyList is non-returning, ;; since exit is non returning. (cons (lambda (x) (fn arg) (exit)) ')))) ;; Gives up control for the next thread waiting to be run. ;; Although it will eventually return, it gives up control ;; and will only regain it when the continuation is called. (define (yield) (call-with-current-continuation ;; Capture the continuation representing THIS call to yield (lambda (thisCont) ;; Stick it on the ready list (set! readyList (append readyList (cons thisCont '))) ;; Get the next thread, and start it running. (let ((cont (car readyList))) (set! readyList (cdr readyList)) ;; Run it. (cont ')))))


It is customary to show the yin-yang puzzle while discussing call/cc:

(let* ((yin ((lambda (cc) (display #\@) cc) (call-with-current-continuation (lambda (c) c)))) (yang ((lambda (cc) (display #\*) cc) (call-with-current-continuation (lambda (c) c))))) (yin yang))

An illustration of the puzzle: Every statements between brackets are the states of yin and yang immediately before (yin yang); The number means whether the 1st continuation or the 2nd to jump. The statement after the number represents the context.

;@* [(yin 1 ) (yang 2 (yin 1 ))] ;@* [(yin 2 (yin 1 )) (yang 2 (yin 2 (yin 1 )))] ;* [(yin 1 ) (yang 2 (yin 2 (yin 1 )))] ;@* [(yin 2 (yin 2 (yin 1 ))) (yang 2 (yin 2 (yin 2 (yin 1 ))))] ;* [(yin 2 (yin 1 )) (yang 2 (yin 2 (yin 2 (yin 1 ))))] ;* [(yin 1 ) (yang 2 (yin 2 (yin 2 (yin 1 ))))] ;@* [(yin 2 (yin 2 (yin 2 (yin 1 )))) (yang 2 (yin 2 (yin 2 (yin 2 (yin 1 )))))] ;... ;...

Read more about this topic:  Call-with-current-continuation

Famous quotes containing the word examples:

    Histories are more full of examples of the fidelity of dogs than of friends.
    Alexander Pope (1688–1744)

    In the examples that I here bring in of what I have [read], heard, done or said, I have refrained from daring to alter even the smallest and most indifferent circumstances. My conscience falsifies not an iota; for my knowledge I cannot answer.
    Michel de Montaigne (1533–1592)

    There are many examples of women that have excelled in learning, and even in war, but this is no reason we should bring ‘em all up to Latin and Greek or else military discipline, instead of needle-work and housewifry.
    Bernard Mandeville (1670–1733)