15-150: Principles of Functional Programming

Lecture 4: Recursion and Structural Induction on Lists, Tail Recursion

In the previous lecture, we introduced SML's predefined datatype   int list   for lists of integers.
An important point is that the list datatype is defined recursively:
An   int list   is one of the following (and nothing else):

  1. Either the empty list (written nil or []),
  2. or of the form  x::xs, with   x : int   and   xs : int list.

Last time and today we wrote some functions taking list arguments and/or returning list values, and we showed how to prove theorems about lists using structural induction.

We discussed tail recursion, a form of recursion that is somewhat like the use of loops in imperative programming. This form of recursion is often used to make functions more efficient.

Terminology:  A function is tail recursive if it is recursive and if it performs no computations after any recursive call that it makes. This means in particular that the function directly returns any value obtained from any recursive call that it makes.   More generally, a function f is said to make a tail call to function g if calling g is the final computation f performs. From that perspective, a recursive function f is tail recursive if any calls to itself are tail calls.

(Clarifying Comment:  If the body of a function contains multiple locations at which a recursive call occurs, then every one of those recursive calls must be a tail call in order for the function to be considered tail recursive.)

Accumulator arguments play an important role in tail recursion. The presence of an accumulator argument in a function forces us to think carefully about the specification of the function and to prove corresponding theorems of correctness.

Key Concepts

Sample Code

Some Notes on Structural Induction

(Those notes also discuss two concepts that we have not yet discussed: datatype declarations and structural induction over trees; we will see these in the next lecture.)

Proof of an extensional equivalence for two implementations of list reversal

Slides from Lecture