What are Continuations?

And why you should care!

Agenda

  • Control flow
  • Introducing CPS
  • An Example

Control Flow

What does this code do?


def foo(a):
    res = ""
    if a > 100:
        res = bar(qux(a))
    else:
        res = baz(a % 7)
    print(res)

def bar(b):
    return b*9

def qux(c):
    return c % 10

def baz(d):
    return d*19
                            

Control Flow

Running a program

Control Flow

An "if statement

Control Flow

Calling a subroutine

Control Flow

Entering the subroutine. Allocate a stack frame to "remember where we were"

Control Flow

Return the value & pop the stack frame

Control Flow

  • if
  • try/catch
  • case/switch
  • while
  • for
  • GOTO

Control Flow


Its what happens next

What happens if you take away function return???

Continuation Passing

Here comes the headache


def foo(a, next):
    step = lambda b : bar(a, b, next)
    baz(step)

def bar(a, b, next):
    next(a + b)

def baz(next):
    next(42)
                        

Continuation Passing

Explicitly declaring what happens next is equivalent to GOTO!

Continuation Passing

Why would you want this??

Implement new control flows

  • Async tasks on a single-threaded runtime (JS Promises)
  • Try/catch in a language without it
  • Early return in a language without it
  • Coroutines

An Example: Early Return

A continuation takes the form of (a -> r) -> r. This is a Functor, Applicative, and Monad

  • type Cont r a = (a -> r) -> r
  • runCont :: Cont r a -> r) -> (a -> r) -> r
  • callCC :: ((a -> Cont r b) -> Cont r a) -> Cont r a

An Example: Early Return


fun :: Int -> String
fun n = (`runCont` id) $ do
    str <- callCC $ \exit1 -> do
        when (n < 10) (exit1 (show n))
        let ns = map digitToInt (show (n `div` 2))
        n' <- callCC $ \exit2 -> do
            when ((length ns) < 3) (exit2 (length ns))
            when ((length ns) < 5) (exit2 n)
            when ((length ns) < 7) $ do
                let ns' = map intToDigit (reverse ns)
                exit1 (dropWhile (=='0') ns')
            return $ sum ns
        return $ "(ns = " ++ (show ns) ++ ") " ++ (show n')
    return $ "Answer: " ++ str