# 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.

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

• Lists defined recursively
• Correspondence between recursive datatype, recursive function clauses, and proof by structural induction
• Tail Recursion
• Accumulator argument

### Some Notes on Structural Induction

(These 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.)