# Class 39: Tail Recursion, Continued

Back to Tail Recursion. On to Variable-Arity Procedures.

Held Tuesday, November 12, 2002

Summary

Today we continue our consideration of tail recursion, including the construction of tail-recursive procedures that build lists.

Related Pages:

Assignments

Notes

• Are there questions on exam 2?
• Any updates I make are documented in the extra credit part.
• Quiz today!

Overview

• A few more notes on tail recursion
• Lab

## Making Procedures Tail-Recursive

• Is tail recursion always better?
• No, not if you do a lot of extra work in each recursive call.
• Consider `add-to-all-2` from the lab. It was significantly slower than the non-tail-recursive version.
• Can all recursive procedures be made tail-recursive?
• Yes, but sometimes it requires a significant amount of work.
• For example, we needed to reverse the result in `select`.
• Consider the following strange procedure:
```(define strange
(lambda (lst)
(if (null? lst) 0
(let ((first (car lst))
(tmp (strange (cdr lst))))
(if (> first tmp)
(- first tmp)
(- tmp first))))))
```
• Consider also the following less-strange procedure
```(define square (lambda (x) (* x x)))
(define exponent
(lambda (val power)
(cond
; Anything to the 0th power is 1.
((zero? power) 1)
; Cool math: x^2n = (x^n)*(x^n)
((even? power) (square (exponent val (/ power 2))))
; Less-cool math: x^(n+1) = x * x^n
(else (* val (exponent val (- power 1)))))))
```

## Some More Notes

• It should be easy to identify non-tail recursive procedures:
• They're recursive.
• In at least one recursive call, you apply some procedure to the result of the recursive call.
• The `filter` procedure defined below is not tail recursive because it applies cons the result of one of the recursive calls.
```(define filter
(lambda (pred? lst)
(cond
((null? lst) null)
((pred? (car lst)) (filter pred? (cdr lst)))
(else (cons (car lst) (filter pred? (cdr lst)))))))
```
• The `largest` procedure defined below is not tail recursive because it applies max to the result of the recursive call.
```(define largest
(lambda (lst)
(if (null? (cdr lst))
(car lst)
(max (car lst) (largest (cdr lst))))))
```
• Yes, we can make both of these procedures tail recursive, but with varying degrees of difficulty.
```(define tr-filter
(lambda (pred? lst)
(let kernel ((unfiltered lst)
(rev-filtered null))
(cond
((null? unfiltered) (reverse rev-filtered))
((pred? (car unfiltered))
(kernel (cdr unfiltered) rev-filtered))
(else (kernel (cdr unfiltered)
(cons (car unfiltered) rev-filtered)))))))

(define tr-largest
(lambda (lst)
(let kernel ((remaining (cdr lst))
(max-so-far (car lst)))
(if (null? remaining) max-so-far
(kernel (cdr remaining)
(max (car remaining) max-so-far))))))
```

## Lab

• Continue the lab.

## History

Thursday, 29 August 2002 [Samuel A. Rebelsky]

Tuesday, 12 November 2002 [Samuel A. Rebelsky]

• Added links to related pages and other introductory material.
• Added first few sample questions.

Back to Tail Recursion. On to Variable-Arity Procedures.

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

This document was generated by Siteweaver on Mon Dec 2 08:41:52 2002.
The source to the document was last modified on Tue Nov 12 09:37:38 2002.
This document may be found at `http://www.cs.grinnell.edu/~rebelsky/Courses/CS151/2002F/Outlines/outline.39.html`.

You may wish to validate this document's HTML ; ; Check with Bobby

Samuel A. Rebelsky, rebelsky@grinnell.edu