Class 09: Continuations, Continued

Back to Continuations, Continued. On to Continuations, Nearly Concluded.

Held Friday, February 12

Summary

• Continuations and tail recursion
• Applications of continuations
• Assignment 2 due.
• Exam 1 distributed. Due Friday, February 19.

Contents

Handouts

Notes

• Assignment 2 is due today.
• I received a lot of questions today that would have been better resolved earlier in the week. Please start your assignments early.
• I will only grade one of the two problems (sorry, no advance notice on which one). You are, however, required to turn in both problems. This is certainly one of the assignments in which I expected you to learn a lot from doing the assignment.
• Any assignment not turned in by 1:20 will be marked late and receive a letter-grade penalty (10%). Any assignment not turned in by 1:20 on Monday will receive a 0.
• An answer key will be available on Monday.
• As you may have noted, the schedule has changed slightly.
• Dan Wislocki says ``Check out http://www.unixguru.com''.

Exponent, revisited

• You may recall that we recently wrote a relatively efficient exponentiation function.
;;; Compute x^n for nonnegative integer n.
(define (exp x n)
(cond
((= n 0) 1)
((even? n) (lambda (x) (* x x) (exp x (/ n 2))))
((odd? n) (* x (exp x (- n 1))))))

• There are two reasons that this is not tail-recursive.
• In the even case, we square the result of the recursive call.
• The the odd case, we multiply the result of the recursive call by x.
• You were asked to think about how to make it tail-recursive.
• We started with the definition of a helper function.
;;; Compute acc*(x^n) for nonnegative integer n.
(define (expacc x n acc) ...)

• Now, what can we do?
• For the base case, we just use acc (since 1*a is a).
• For the odd case, we can write
((odd? n) (expacc x n (* acc x)))

• Since acc*(x^(k+1)) = (acc*x)*(x^k)
• How do you want to handle the even case? Recall that we've been using the formula (x^(2*k)) = (x^k)^2. Are there others we might use?

Continuations, continued

• As we saw in previous classes, continuations are basically functions that represent ``what to do next''.
• We can create continuations ourselves (using a programming technique known as continuation-passing style or CPS).
• In Scheme, it is also possible to get the current continuation with call/cc.
• (call/cc fun) calls fun with the current continuation.
• Often, we use continuation-passing style to make the order of evaluation explicit. Because Scheme uses an ``evaluate arguments before calling a function'' order of evaluation, we can be confident that if we apply a continuation to an expression, the expression will be evaluated first.
• We'll begin with an odd function seta, that gets the next value from the list input
> (define (get)
(let ((result (car input)))
(begin
(set! input (cdr input))
result)))
> (set! input '(1 2 3))
> (get)
1
> (get)
2
> (get)
3

• Now, what's the value of (- (get) (get))? (Assuming that input is currently (1 2 3).)
• It depends on the order of evaluation.
• Suppose we wanted to evaluate the second (get) first. We could make that explicit.
> ((lambda (second) (- (get) second)) (get))

• Since we've given the context of the second (get), we might as well provide one for the first.
> (set! input '(1 2 3))
> ((lambda (b)
((lambda (a)
(- a b))
(get)))
(get))
1

• Similarly, if we wanted to do the first (get) first, we might write
> (set! input '(1 2 3))
> ((lambda (a)
((lambda (b)
(- a b))
(get)))
(get))
-1

Tail recursion with CPS

• In order to do the multiplications in factorial in ``the right order'', we can use continuation-passing style.
• How? We might instead accumulate ``what's left to do''.
(define (factorial n)
(letrec
((factcps (lambda (n cont)
(if (= n 0) (cont 1)
(factcps (- n 1)
(lambda (subfact)
(cont (* n subfact))))))))
(factcps n (lambda (n) n))))

• Note that we're basically putting a stack into the recursive call.
• Can you write a tail-recursive efficient exponential without CPS? With CPS? How about an iterative version?

History

• Created Tuesday, January 19, 1999 as a blank outline.
• Filled in the details on Thursday, February 11, 1999.
• Removed some of those details on Monday, February 15, 1999. (Moved them to the next outline.)

Back to Continuations, Continued. On to Continuations, Nearly Concluded.

Disclaimer Often, these pages were created ``on the fly'' with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.