Programming Languages (CSC-302 98S)

[Instructions] [Search] [Current] [Changes] [Syllabus] [Handouts] [Outlines] [Assignments]


Outline of Class 23: Continuations

Held: Monday, March 30, 1998

Administrivia

uses the r-value of x on the left-hand side and the l-value of x on the right-hand side. Why? Because the index in the array is an integer. To get that integer, we need to dereference x (taking the r-value). However, since the value we want to store is a reference to an integer, we do not dereference the x on the right-hand side and therefore use its l-value. If you gave a similar answer (including explanation), let me know and you'll get full credit. If you only wrote the code and didn't give an explanation, you also got 25/25 (although I was seriously considering giving you 20/25).

Notes on the Assignments


Exercise: Writing Testing Routines

In groups of approximately four, write a testing predicate for the quicksort routine that we developed before break. Your predicate should return true if the sorting routine can sort any list of integers up to size fifteen and false if it cannot sort any such list. Your routine should be sufficiently robust that you'd be willing to stake your grade on it (that is, that any sorting routine that passes the predicate will correctly sort any list of integers of size less-than or equal to fifteen and that any sorting routine that fails the predicate will fail on at least one such list).

Turn in your predicate.

Continuations

Exercise

You should work on this exercise in groups of approximately four. Turn in a sheet with your answers.

As you may know, one of the criticisms of recursive program design is that it is "inefficient" because of the space required for stack frames and the time required to add and remove those stack frames. One solution to this problem is to use tail-recursive functions in which "nothing" is done with the result of the recursive call (other than returning it). With such functions, it is possible to replace the contents of the stack frame (updating any parameters with their new values) rather than to create a new stack frame.

Consider the factorial function, typically written as

(define (fact n)
  (if (= n 0) 1
      (* n (fact (- n 1)))))

One way to make this tail-recursive is to define a helper function that takes a second accumulator as a parameter and have that accumulator accumulate the multiplication of n*(n-1)*(n-2)*.... Such a function might look like

(define (tr-fact n)
  (tr-fact-helper n 1))
(define (tr-fact-helper n acc)
  (if (= n 0) acc
      (tr-fact-helper (- n 1) (* n acc))))

There are a few problems with this strategy. First, it is not sufficiently general (not all recursive functions can use a numerical accumulator). Second, it does not do the operations in the same order (the original version multiplied 1*1*2*3*...*n. This multiplies 1*n*(n-1)*...1.).

To develop a more general strategy for making recursive functions tail-recursive, we can rely on continuations. Rather than passing an accumulator in each recursive call, we'll instead pass a continuation that describes what to do with the result. Here's a sketch

(define (cfact n)
  (cfact-helper n (lambda (x) x)))
(define (cfact-helper n cont)
  (if (= n 0)
      (cont 1)
      (cfact-helper (- n 1) ???)))

Your goal is to figure out what to plug in for the ???. How can you do so? You might first determine what happens when you call (cfact 0). Next, consider what you know about continuations. For example, in the original definition of factorial, if the continuation for (fact 5) is C, what is the continuation for (fact 4)?

Use your answer to that question to help you fill in the question marks.

Test your answer in the Scheme interpreter.

Run the new, continuation-based (cfact 3) by hand to see what happens. What do you observe?

Can you use this strategy for other common recursive functions? Why or why not?


On to More Topics in Scheme
Back to Other Issues in Functional Languages and Scheme
Outlines: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
Current position in syllabus


[Instructions] [Search] [Current] [Changes] [Syllabus] [Handouts] [Outlines] [Assignments]

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.

Source text last modified Thu May 7 20:29:41 1998.

This page generated on Thu May 7 20:34:43 1998 by SiteWeaver.

Contact our webmaster at rebelsky@math.grin.edu