20-CS-4003-001 Organization of Programming Languages Fall 2017
Miscellaneous Ideas

Lambda calculus, Type theory, Formal semantics, Program analysis

    Prev     Next     All lectures        Code

Continuations

;; an infinite recursion
(define succ
  (lambda (n)
    (cons n (succ (+ n 1)))))

;; (succ 1) -> aborts on stack depth

;; a continuation is grabbed by lambda ()
(define succ$
  (lambda (n)
    (cons n (lambda () (succ$ (+ n 1))))))

;; the procedure is the continuation
(succ$ 1) ;; (1 . #[procedure])

;; easy access to the continuation
(define rest (cdr (succ$ 1))) ;; #[procedure]

;; invoke the continuation
(rest) ;; (2 . #[procedure]) - a new continuation

;; invoke four continuations - returns 5
(car ((cdr ((cdr ((cdr ((cdr (succ$ 1))))))))))

;; routine to pull out the first
;; n tokens of a stream
;; ex: (take$ (succ$ 1) 10)
;; creates a list
(define take$
  (lambda (s n)
    (if (zero? n)
        '()
        (cons (car s) (take$ ((cdr s)) (- n 1))))))

;; routine to return the nth token in a stream
;; (take_nth$ (succ$ 1) 10) -> 10
(define take_nth$
  (lambda (s n)
    (if (= n 1)
        (car s)
        (take_nth$ ((cdr s)) (- n 1)))))

;; factorial in non-continuation passing style
;; (fact3 -1) -> out of memory error
;; (fact3 8) -> (40320 5040 720 120 24 6 2 1)
(define fact3
  (lambda (p)
    (letrec
      ((fact
         (lambda (n acc)
           (if (> n p)
               acc
               (fact (+ n 1)
                     (cons (* n (car acc)) acc))))))
      (fact 2 '(1)))))

;; continuation passing style
;; (take$ (fact3$ 1 1) 6) -> (1 2 6 24 120 720)
;; (take_nth$ (fact3$ 1 1) 8) -> 40320
(define fact3$
  (lambda (n acc)
    (cons (* n acc)
          (lambda () (fact3$ (+ n 1) (* n acc))))))

;; put it inside a letrec
(define fact4$
  (lambda (n)
    (letrec
      ((fact$
         (lambda (n acc)
           (cons (* n acc)
                 (lambda () 
                   (fact$ (+ n 1) (* n acc)))))))
      (take$ (fact$ 1 1) n))))
 -  continuation: a construct that gives a programming language the ability to save the execution state at any point and return to that point at a later time in the program.

Function succ is an infinite recursion aiming to produce a list of all positive integers if the argument is 1 - it aborts with stack overflow. Function succ$ does the same thing except that the recursive call to succ$ is wrapped inside a lambda. This stops execution of (succ$ 1) with a cons pair consisting of a first token (1) plus a continuation that is the thunk (lambda () ...) which is identified by scheme as a #[procedure]. The continuation can be invoked to continue execution for one more step like this: ((cdr (succ$ 1))) which returns (2 . #[procedure]), yet another continuation.

Function take$ invokes the continuations any number of times, assembling a list of first tokens on the way. Function take_nth$ does the same except it returns the last element only. These are utilities that are used below.

Function fact3 computes a list of consecutive factorials in reverse order. It is not written in continuation passing style. The invocation (fact3 -1) results in no output. Function fact3$ does the same but it written in CPS. It can be coupled with take$ or take_nth$. It is used in a letrec in fact4$. The invocation (fact4$ -1) returns a value.