MENTAL
 Main Menu
 Applications
 Computer Science
 Continuations


14. Continued
 CONTINUATIONS
(CONTINUATION-
PASSING
STYLE, CPS)

Functional parameterization of functions

"Continuation-passing style is a notation notation that makes explicit every aspect of the control and data control and data flow" (Andrew W. Appel).



The CPS Technique

Definición

CPS is a functional programming technique consisting of the following: The function c with argument r represents what "remains to be done" (after obtaining the first result r) to complete the final result of the function f. That is why c is called "continuation function" or, simply, "continuation". And the function that includes as parameter a continuation function is called "function with continuation" or "CPS function".


Difference between the functions f(a, c) and c(f(a))

In both cases the result is the same, but there are important differences:
  1. In the first function, c is a parameter and in the second one it is not.

  2. In the first function, after executing and obtaining the result r, c (with argument r) is called. Subsequently, the control is returned. In the second function, after obtaining r, there is return (of the result and of the control) to the function c.

  3. In the first case, there may be higher-order continuations, i.e., the continuation could in turn invoke another function with continuation, which in turn could call another function with continuation, etc., so the function is functionally open. In the second case, the function is functionally closed.

Implementation in MENTAL

Specification

The CPS function in MENTAL can be represented in the classical form (with parameters in parentheses) f(x c) being: Definition:
Example
  1. Normal style.

    Function definition:
    ⟨( square(x) = x*x )⟩

    Function usage:
    square(4) // ev. 4*4 ev. 16

  2. CPS.

    Function definition (an additional parameter is added):
    ⟨( square(x c) = c(x*x) )⟩

    Definition of a function continued:
    ⟨( sum5(x) = x+5 )⟩

    Function usage:
    square(4 add5) // ev. add5(4*4) ev. add5(16) ev. 16+5 ev. 21

    Definition of another function continued:
    ⟨( prod5(x) = 5*x )⟩

    Using the function with the new function continued:
    square(4 prod5) // ev. prod5(4*4) ev. prod5(16) ev. 5*16 ev. 80

Continuation function with parameters

The function c represents a function with any number of parameters. For example, generalizing the above example by one parameter, An example of a continuation function with two parameters is the following: Note that it is necessary to separate the parameters of the continuation function from the parameter corresponding to the result of the CPS function.


Null continuation

In the CPS function if we use as continuation the null expression (θ), we have, for example: Therefore, when the continuation is null, we are in the normal style.


Bound and free variables in CPS

A CPS function −like any generic parameterized expression− has variables of two types: Example:
Continuation in recursive functions

Applying a continuation to a recursive function produces a new (extended) function that applies to the original recursive function.

Example with factorial:
  1. Normal style:

    ⟨( fac(n) = (1 ← n=1 →' n*fac(n−1))) )⟩

    fac(4) // ev. 4*3*2*1 ev. 24


  2. CPS:

    ⟨( facx(n c) = (c(fac(n))) )⟩

    If we use the following function

    ⟨( linear(a b)(x) = (a*x + b) )⟩

    we have:

    facx(4 linear(2 5)) // ev. linear(2 5)(24) ev. 224+5 ev. 53
Example with Fibonacci sequence: 1, 1, 2, 2, 3, 5, 8, 13, ...
  1. Normal style:

    ⟨( fibo(n) = (1 ← n>2 →' (fibo(n−1) + fibo(n−& 2)))) )⟩

    fibo(1) // ev. 1
    fibo(2) // ev. 1
    fibo(3) // ev. 2
    fibo(4) // ev. 3
    fibo(5) // ev. 5
    ...


  2. CPS:

    ⟨( fibox(n c) = c(fibo(n)) )⟩

    If we use the following function

    ⟨( double(x) = 2*x )⟩

    we have:

    fibox(1 double) // ev. double(1) ev. 2
    fibox(2 double) // ev. double(1) ev. 2
    fibox(3 double) // ev. double(2) ev. 4
    fibox(4 double) // ev. double(3) ev. 6
    fibox(5 double) // ev. double(5) ev. 10
    ...


    What you get are the double values of the Fibonacci sequence.

Higher order continuations

A continuation function can, in turn, have another continuation function. The general form for two continuation functions is

⟨( f(x c1 c2) = c2(c1(f(x))) )⟩

For example: Definition of a function continuation c1: Definition of a function continuation c2: Using the function: The higher-order continuation functions could, in turn, have parameters.


Beyond CPS. The parameterization of expressions

The CPS technique is the functional parameterization of functions, but it is a particular case of the general case of adding parameters to expressions, which can be done in MENTAL. Examples of function on intermediate results (not on the final result):
  1. Factorial:

    ⟨( fac(n c) = (c(1) ← n=1 →' c(n)*fac(n−1 c)))) )⟩

      fac(1 c) // ev. c(1)
      fac(2 c) // ev. c(2)*c(1)
      fac(3 c) // ev. c(3)*c(2)*c(1)
      ...

    If c=θ, we have the normal factorial function.

    If we use the function ⟨( double(x) = x*2 )⟩, we have:

      fac(1 double) // ev. double(1) ev. 2

      fac(2 double) // ev. double(2)*double(1) ev. 4*2 ev. 8

      fac(3 double) // ev. double(3) * double(2) * double(1) ev. 6*4*2 ev. 48 ...

  2. Fibonacci Sequence: 1, 1, 2, 2, 3, 5, 8, 13, ...

    ⟨( fibo(n c) = (c(1) ← n>2 →' c(fibo(n−1 c) + fibo(n−2 cb>)))) )⟩

      fibo(1 c) // ev. c(1)
      fibo(2 c) // ev. c(1)

      fibo(3 c) // ev. c(fibo(2 c) + fibo(1 c)) ev. c(2*c(1))

      fibo(4 c) // ev. c(fibo(3 c) + fibo(2 c)) ev. c(c(2*c(1)) + c(1))
      ...

    If c=θ, we have the normal Fibonacci function.

    If we use the same function above (double) as c, we have:

      fibo(1 double) // ev. double(1) ev. 2

      fibo(2 double) // ev. double(1) ev. 2

      fibo(3 double) // ev. double(2 + 2) ev. 8

      fibo(4 double) // ev. double(2 + 8) ev. 20
      ...
Examples of data parameterization:
  1. ⟨(unodos(c) = c(12))⟩

    Parameterization using a function:

      ⟨(double(x) = 2*x)⟩

      unodos(double) // ev. 2*12 ev. 24

    Parameterization using data:

      unodos(123) // ev. 123(12)

  2. ⟨( record(c) = (c(6) c(12) c(9) c(17) c(8))) )⟩

    Parameterization using a function:

      ⟨( selec(n)(x) = (x<nx) )⟩ // select x if less than n

      register(select(10)) // ev. (6 9 8)

    Parameterization using data:

      register(abc)) // ev.(abc(6) abc(12) abc(9) abc(17) abc(8))

  3. ⟨( log(c) = (6 12 9 17 8)c )⟩

    Parameterization using a function:

      ⟨( selec(s)(x) = ( xs ) )⟩ // s is the selection criterion

      register(select(>9)) // ev. (6 12 9 17 8)⇓(>9) ev. (12 17)

    Parameterization using data:

      record(u v w) // ev. (6 12 9 17 8)(u v w)

Conclusions

In traditional programming languages, f is fixed (it cannot be variable). In MENTAL, it can be variable, so the concept of continuation is irrelevant, since it makes no difference whether the continuation is included as a parameter or as a function. For example, Variable function name: Function name continuation variable: Variable function name and variable continuation function name:

Addenda

Main features of the CPS technique
Applications of the CPS technique

The CPS technique was born in the late 1960s. Since then, in addition to its aforementioned application in the development of compilers and interpreters, it has also been applied in a variety of areas:
Bibliography