Fundamentals of CS I (CS151 2001S) : Outlines

[Current]
[Discussions]
[Glance]
[Honesty]
[Instructions]
[Links]
[News]
[Search]
[Syllabus]
**Primary**

[Examples]
[Exams]
[Handouts]
[Homework]
[Labs]
[Outlines]
[Quizzes]
[Readings]
[Reference]
**Sets**

[Blackboard]
[Scheme Report]
[SamR's Schedule]
[Rebelsky/Fall 2000]
[Walker/Fall2000]
[Stone/Spring2000]
**Links**

Reading: Tail Recursion. Lab: Tail Recursion. Back to Script-Fu Concluded. On to Tail Recursion, Continued.

**Held** Monday, April 9, 2001

**Summary**

Today we revisit recursion and consider a more efficient way to write
recursive procedures. This new technique is called *tail recursion*.

**Notes**

- Anne is changing tonight's office hours to 7:30-8:30.
- For Wednesday, read Variable-Arity Procedures.
- As some of you have noted, I regularly make PDF files for readings and labs. Does anyone use those? Does anyone want to?
- Are there questions on the exam?
- I'd recommend that you break problem 1 up into parts, and do each part separately.
- You can have a precondition in problem 1 that states the maximum length of a first or last name. (Extra credit for handling an arbitrary width.)
- You may want to review the string procedures for hints on how to do left- and right- justification.
- For problem 2, I want you to
*change*the vector given as a parameter, and not return a new vector.

- Here's what I expected for intersect:
(define intersect (lambda (set1 set2) ((remove (complement (right-section member set2))) set1)))

- In English: Remove from set1 all values that are not in set 2.
- Why did I give this problem? Because I wanted you to see that the higher-order procedures give us a very different way of thinking about problem solving. Once you've written good helpers, your first inclination no longer has to be one that involves a standard recursive pattern.

**Overview**

- Kinds of recursion
- Why do tail recursion
- Generating lists tail-recursively
- Lab

- Recursion in which you do something with the recursive result.
- E.g., definition of
`add-to-all`

,`factorial`

, traditional right-associative`sum`

.

- E.g., definition of
- Recursion in which you simply return the recursive result, unchanged.
- E.g.,
`member?`

, the left-associative`sum`

.

- E.g.,
- The latter kind of recursion is called
*tail recursion*and, in Scheme, is likely to be faster. Why? - Let's look at the two versions of
`sum`

(in class).- Version 1, right associative, not tail recursive.
(define sumr (lambda (values) (if (null? values) 0 (+ (car values) (sumr (cdr values))))))

+ Version 2, left associative, tail recursive. (define suml (lambda (values) (suml-helper values 0))) (define suml-helper (lambda (remaining-values partial-sum) (if (null? remaining-values) partial-sum (suml-helper (cdr remaining-values) (+ partial-sum (car remaining-values))))))

- Version 1, right associative, not tail recursive.
- Let's sum the list
`(1 2 3 4)`

and see if one seems to be easier to deal with.- Right associative
(sumr (1 2 3 4)) --> (+ 1 (sumr (2 3 4))) --> (+ 1 (+ 2 (sumr (3 4)))) --> (+ 1 (+ 2 (+ 3 (sumr (4))))) --> (+ 1 (+ 2 (+ 3 (+ 4 (sumr ()))))) --> (+ 1 (+ 2 (+ 3 (+ 4 0)))) --> (+ 1 (+ 2 (+ 3 4))) --> (+ 1 (+ 2 7)) --> (+ 1 9) --> 10

- Left associative
(suml (1 2 3 4)) --> (suml-helper (1 2 3 4) 0) --> (suml-helper (2 3 4) 1) --> (suml-helper (3 4) 3) --> (suml-helper (4) 6) --> (suml-helper () 10) --> 10

- Right associative
- Which would you prefer to evaluate by hand?
- In the right-associative case, Scheme needs to remember the
things to do once the recursion reaches the base case

.- Remembering that stuff takes extra memory and time.

- Hence, tail-recursive procedures are normally quicker than non-tail-recursive procedures.

- The normal strategy for making procedures tail recursive is the
one we used for
`suml`

:- Make a helper procedure with one additional parameter.
- The additional parameter
accumulates

partial solutions. Hence, we often call it an*accumulator*.

- You can often transform a non-tail-recursive (but recursive) procedure
in to a tail-recursive procedure:
- Build that helper with an extra parameter.
- The accumulator normally starts out with the value from the
old

base case (the one in the non-tail-recursive procedure). - The operation used to update the accumulator is similar to (but not necessarily identical to) the one used in the standard recursive call.

- While tail recursion is generally a good thing, it's a bad idea
to spend lots of extra computational effort on building the
accumulated partial result.
- The problem appears most frequently in procedures that build lists.

- Consider the problem of adding two to each value in a list.
- Suppose our accumulator contains all the values we've added two to.
- Then at each step, we'll need to put the next value
*at the end*of the accumulator.- How do you add to the end of a list?
- How much computational effort does it involve?

- You'll find that your procedure spends a lot of time walking through the accumulated result.
- Can we do something better? Yes. Accumulate the
*reverse*of the desired result.- Updating at each step is each; just cons to the front.
- We do need to spend some extra effort at the end to reverse that result.

- Alternately, we can reverse the parameter before calling the helper.
- See the reading for more details.

Back to Script-Fu Concluded. On to Tail Recursion, Continued.

[Current]
[Discussions]
[Glance]
[Honesty]
[Instructions]
[Links]
[News]
[Search]
[Syllabus]
**Primary**

[Examples]
[Exams]
[Handouts]
[Homework]
[Labs]
[Outlines]
[Quizzes]
[Readings]
[Reference]
**Sets**

[Blackboard]
[Scheme Report]
[SamR's Schedule]
[Rebelsky/Fall 2000]
[Walker/Fall2000]
[Stone/Spring2000]
**Links**

**Disclaimer**:
I usually create these pages on the fly. This means that they
are rarely proofread and may contain bad grammar and incorrect details.
It also means that I may update them regularly (see the history for
more details). Feel free to contact me with any suggestions for changes.

This page was generated by Siteweaver on Wed May 5 12:15:06 2004.

This page may be found at `http://www.cs.grinnell.edu/~rebelsky/Courses/CS151/2001S/outline.37.html`

.

You may validate
this page's HTML.

The source was last modified Tue Jan 23 16:01:58 2001.