Introduction to Iteration and Recursion
Recursive Programs
Recursion is a technique for writing programs. Even when we think we know a word, checking out a dictionary definition can help us to understand it better. You can check out the definition of recursion at MerriamWebster Online, which dates the first known use of "recursion" to 1790. Here is that definition, edited lightly for our purposes:
re · cur · sion
 RETURN sense 1: to go back or come back again
 the determination of a succession of elements (such as numbers or functions) by operation on one or more preceding elements according to a rule or formula involving a finite number of steps
 a computer programming technique involving the use of ... a function or algorithm that calls itself ...
To recur is to go back, in thought or discourse. A function can do that.
In computer science, a recursive program is one that:
 immediately returns an answer for one or more simple problems, and
 computes answers for more complex problems in terms of the answers to simpler problems, for which it calls itself.
As a result of the second part of this definition, we can see that a recursive program is defined, in part, in terms of itself. In practice, we create a function that calls itself.
We sometimes use recursive relationships to understand mathematical properties. For example, we can examine a sequence of values containing a number raised to a power and see a pattern:
power(x, 0) = 1 power(x, 1) = 1 * x = x * power(x, 0) power(x, 2) = 1 * x * x = x * power(x, 1) power(x, 3) = 1 * x * x * x = x * power(x, 2) ...
We can turn this into something more usable by turning the power itself into a variable and using an inductive definition to make the pattern explicit:
power(x, 0) = 1 power(x, n) = x * power(x, n1)
In fact, there are programming languages — such as Prolog and Haskell — in which you write the recursive equations just like that!
In Racket, we would write:
(define power ; behaves like the builtin function expt (lambda (x n) (if (zero? n) 1 (* x (power n (sub1 n))))))
The fundamental idea behind recursion is this: If a problem can be defined in terms of a similar, yet simpler problem, recursion may be a useful tool for expressing a solution.
Iteration and Recursion
"O, thou hast damnable iteration and
are indeed able to corrupt a saint."
— Falstaff,
in Shakespeare's Henry IV
Most programmers learn to write loops first and then see recursion as a more difficult way to do things they can already do. But I think you'll find iteration and recursion are really pretty similar. More importantly, you think about the same things no matter which one you are using.
Consider the task described in the song "99 Bottles of Beer on the Wall".
 If n = 0, there is nothing left to do but sing the last verse.
 If n > 0, there is a bottle of beer to take down and pass around, plus n1 more bottles of beer on the wall.
How might we solve this task with a loop?
n = 99; while (n > 0) { take_one_down(); pass_it_around(); n; } sing_last_verse();
Notice that you get to solve "n1 bottles" with the same code that solved "n bottles". That's exactly what we do when we write a recursive solution:
bottles_of_beer(99)
where:
bottles_of_beer(0) = sing_last_verse() bottles_of_beer(n) = take_one_down() pass_it_around() bottles_of_beer(n1)
In both cases, you have to answer the same questions:
 What do you do when you stop?

How do you know to keep going? or
How do you know when to stop?  What do you do with each item?
 What gets smaller on each pass?
Iteration and recursion really are the same kind of process. You may even have noticed that the dictionary definition of "recursion" we saw earlier says as much. The third entry of that definition ends with the phrase compare iteration!
Be not afraid. If you can write a loop, then you, too, can write recursive functions.
(See this footnote for the source of this example and for a little unexpected goodness.)
The Structure of Recursive Programs
More formally, we will say that every recursive program consists of:
 one or more base cases that terminate computation in a predefined answer, and
 one or more recursive cases that compute solutions in terms of simpler problems. The "limit" of these smaller problems is one of the base cases.
The base cases are often pretty straightforward, but we still have to think. They encode our understanding of the problem by recording the answer to the smallest problem(s) in the domain.
Each recursive case consists of three steps:
 Split the data into smaller pieces.
 Solve the pieces.
 Combine the solutions for the parts into a single solution for the original argument.
This is usually where the descriptions of recursion end in our textbooks. "Okay," you might say, "great. But how do I do that?" The goal of the next few weeks is to help you feel this TL;DR in your bones:
Recursion doesn't have to be scary.
Sometimes, it's all about the data.
In particular, there are rules that help us to think about each of these steps:

We split the data into subproblems based on the type of
the argument our function receives. For example:

break a pair into parts, using
car
andcdr

break a list into parts, using
first
andrest

break a positive integer
n
into parts, such as 1 andn  1

break a pair into parts, using

We will often define our data so that the "big" subproblem is
topologically similar
to the original problem. For example, the
rest
of a list is also a list. The numbern1
is a also a number that can be decomposed. We will take advantage of this similarity by solving the "big" subproblem with a recursive call. 
We combine the solutions for the subparts based on the
type of value returned by the function. For example:
 assemble a list from its parts, using
cons
 assemble an integer from its parts, using
+
 assemble a boolean from its parts, using
and
cons
, but sometimes we need to use other listproducing functions such aslist
orappend
. A number can be assembled usingmax
or some other binary operator. A boolean can be assembled usingor
or some other boolean function.  assemble a list from its parts, using
The driver for this process is the the type of the arguments that our function processes. This is where inductive specifications can help.
Note on Iteration and Recursion
I adopted my "99 Bottles of Beer on the Wall" example from this message on an Erlang mailing list. (Erlang is a cool programming language: not quite functional, not quite imperative. It handles concurrency as a primitive!)
That message continues with a bit of news that surprises many programmers who grew up with iteration before learning recursion: Iteration (looping) is a special case of recursion — with limits.
Take a look at our examples above. In the loop, we always handle the one bottle first, then the remaining n1 bottles. But in the recursive function, we could make the recursive call first to handle the n1 bottles first, and then handle the one bottle last. We could even make the call between "take one down" and "pass it around", and interleave the activities! Try that with a loop.
In both iteration and recursion, a program handles an arbitrary number of steps with a single piece of code. This code either branches to the top of a loop (an implicit jump) or makes a function call (an explicit jump) — and reenters itself, so that one piece of code handles any number of things. In both cases, you have to make sure that some measure of the problem size (the length of a list, the number of things left to work on, the size of a tree, etc.) is strictly smaller every time you enter it.
But the function call is more powerful. As the creator of
Scheme wrote back in the 1970s, lambda
is the
ultimate goto
.
Note on Crater Lake
Take a close look at this image. It always makes me smile.
The big island is Luzon, one of the Philippine Islands. In the middle of Luzon is Lake Taal. Inside Lake Taal is Vulcano Island. Notice Crater Lake, the dot of water in the middle of Vulcano Island. Crater Lake holds a unique distinction. It is the largest lake on an island in a lake on an island in the world.
How's that for recursion?
This is a bit more complicated than the simplest recursion. We have a lake on an island in a lake on an island. Two different kinds of objects are recurring back and forth between one another. As we learn in a couple of sessions, this is a special kind of recursion, worthy of its own programming technique!
You can see this image along with a few other fun lake/island combinations at The Island and Lake Combination.