Call-with-current-continuation
Encyclopedia
In functional programming
Functional programming
In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state...

, the function call-with-current-continuation, commonly abbreviated call/cc, is a control operator that originated in its current form in the Scheme programming language and now exists in several other programming languages.

Taking a function f as its only argument, call/cc takes the current continuation
Continuation
In computer science and programming, a continuation is an abstract representation of the control state of a computer program. A continuation reifies the program control state, i.e...

 (i.e., a "snapshot" of the current control context or control state of the program) as an object and applies f to it. The continuation object is a first-class value and is represented as a function, with function application
Function application
In mathematics, function application is the act of applying a function to an argument from its domain so as to obtain the corresponding value from its range.-Representation:...

 as its only operation. When a continuation object is applied to an argument, the existing continuation is eliminated and the applied continuation is restored in its place, so that the program flow will continue at the point at which the continuation was captured and the argument of the continuation will become the "return value" of the call/cc invocation. Continuations created with call/cc may be called more than once, and even from outside the dynamic extent of the call/cc application.

Making this type of implicit program state visible as an object is known in computer science as reification
Reification (computer science)
Reification is the process by which an abstract idea about a computer program is turned into an explicit data model or other object created in a programming language. A computable/addressable object — a resource — is created in a system as a proxy for a non computable/addressable object...

. (Note that Scheme does not syntactically distinguish continuation application from function application.)

With call/cc a programmer can implement a variety of complex control operators from other languages via a few lines of code, e.g., McCarthy
John McCarthy (computer scientist)
John McCarthy was an American computer scientist and cognitive scientist. He coined the term "artificial intelligence" , invented the Lisp programming language and was highly influential in the early development of AI.McCarthy also influenced other areas of computing such as time sharing systems...

's amb operator for non-deterministic choice
Nondeterministic programming
A nondeterministic programming language is a language which can specify, at certain points in the program , various alternatives for program flow...

, Prolog
Prolog
Prolog is a general purpose logic programming language associated with artificial intelligence and computational linguistics.Prolog has its roots in first-order logic, a formal logic, and unlike many other programming languages, Prolog is declarative: the program logic is expressed in terms of...

-style backtracking
Backtracking
Backtracking is a general algorithm for finding all solutions to some computational problem, that incrementally builds candidates to the solutions, and abandons each partial candidate c as soon as it determines that c cannot possibly be completed to a valid solution.The classic textbook example...

, Simula 67-style coroutine
Coroutine
Coroutines are computer program components that generalize subroutines to allow multiple entry points for suspending and resuming execution at certain locations...

s and generalizations thereof, Icon-style generator
Generator (computer science)
In computer science, a generator is a special routine that can be used to control the iteration behaviour of a loop. A generator is very similar to a function that returns an array, in that a generator has parameters, can be called, and generates a sequence of values...

s, or engine
Engine (computer science)
An engine is a continuation-based construct that provides timed preemption. Engines which can contain other engines are sometimes called nesters and engines which don't have this ability are then called flat engines or "solo engines" . To implement timed preemption there needs to be a clock. This...

s and thread
Thread (computer science)
In computer science, a thread of execution is the smallest unit of processing that can be scheduled by an operating system. The implementation of threads and processes differs from one operating system to another, but in most cases, a thread is contained inside a process...

s.

Relation to non-constructive logic

The Curry-Howard correspondence between proofs and programs relates call/cc to Peirce's law
Peirce's law
In logic, Peirce's law is named after the philosopher and logician Charles Sanders Peirce. It was taken as an axiom in his first axiomatisation of propositional logic. It can be thought of as the law of excluded middle written in a form that involves only one sort of connective, namely...

, which extends intuitionistic logic
Intuitionistic logic
Intuitionistic logic, or constructive logic, is a symbolic logic system differing from classical logic in its definition of the meaning of a statement being true. In classical logic, all well-formed statements are assumed to be either true or false, even if we do not have a proof of either...

 to non-constructive, classical logic
Classical logic
Classical logic identifies a class of formal logics that have been most intensively studied and most widely used. The class is sometimes called standard logic as well...

: ((α → β) → α) → α. Here, ((α → β) → α) is the type of the function f, which can either return a value of type α directly or apply an argument to the continuation of type (α → β). Since the existing context is deleted when the continuation is applied, the type β is never used and may be taken to be ⊥.

The principle of double negative elimination
Double negative elimination
In propositional logic, the inference rules double negative elimination allow deriving the double negative equivalent by adding or removing a pair of negation signs...

 ((α → ⊥) → ⊥) → α is comparable to a variant of call-cc which expects its argument f to always evaluate the current continuation without normally returning a value.

Embeddings of classical logic into intuitionistic logic are related to continuation passing style translation.

Examples

As shown by the following example, call/cc can be used to emulate the functionality of the return statement
Return statement
In computer programming, a return statement causes execution to leave the current subroutine and resume at the point in the code immediately after where the subroutine was called, known as its return address. The return address is saved, usually on the process's call stack, as part of the operation...

 known from
C
C (programming language)
C is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....

-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:

[LISTOF X] -> ( -> 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 3 4 5 6 7 8 9)))

(generate-digit)
(generate-digit)


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 [LISTOF X], 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-continuatio
in 25 lines of schem

The list of threads waiting to run. This is a list of on
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 threa
waiting to be run, it causes the next thread to run if ther
is any left to run, otherwise it calls the original exi
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 give
argument and forks it off. The forked function's ne
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 contro
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))

External links

The source of this article is wikipedia, the free encyclopedia.  The text of this article is licensed under the GFDL.
 
x
OK