---
# System prepended metadata

title: Recursion

---

# Recursion

([home](https://github.com/alexhkurz/introduction-to-programming/blob/master/README.md) ... [previous](https://hackmd.io/@alexhkurz/H1o4Mcr6L) ... [next](https://hackmd.io/@alexhkurz/ryiCiDs08))

In the last session we have seen both the mathematical definition of the Fibonacci numbers

\begin{align}
fib(0) & = 0\\
fib(1) & = 1\\
fib(n+2) & = fib(n) + fib(n+1)
\end{align}

as well as an implementation [iterative_fib.py](https://github.com/alexhkurz/introduction-to-programming/blob/master/src/iterative_fib.py):

	def fib(n):
	    fib_one = 0
	    fib_two = 1
	    for i in range(0,n+1):
	        if i == 0:
	            fib = fib_one
	        elif i == 1:
	            fib = fib_two
	        else:
	            fib = fib_one + fib_two
	            fib_one = fib_two
	            fib_two = fib
	    return fib        
    
Both the mathematics and the program are two precise definitions of $fib(n)$. 

But if you compare the two, the program is more difficult to read. In fact, most of the program consists of what we might call "bookkeeping". The mathematical definition
- simply lists the 3 relevant patterns

and 

- does not need if-then-else
- does not need the auxiliary variables `i`, `fib_one`, `fib_two`, `fib`
- does not need assignments

To appreciate the point about assignment, recall how the mathematical equality $=$ is different from assignment `=`: 
- Mathematically equality knows nothing about time.
$$fib(n+2) = fib(n) + fib(n+1)$$ 

    defines an "eternal truth" that holds for all natural numbers $n$.
- On the other hand, 

            fib = fib_one + fib_two

        
    is a command describing how the variable `fib` changes in time when the command is executed.

Wouldn't it be nice if we could just write the mathematical definition in Python and leave it to the machine (or interpreter/compiler more precisely) to generate the necessary computation from it?

## Computing with recursive definitions

We first want to understand whether it is possible at all to turn a mathematical definition such as

\begin{align}
fib(0) & = 0\\
fib(1) & = 1\\
fib(n+2) & = fib(n) + fib(n+1)
\end{align}

into a computation in a principled way that could be automatised.

**Remark:** This style of definition is called **recursive**, because, in order to define $fib(n+2)$ we are *recurring* to the values $fib(n)$ and $fib(n+1)$. This definition looks almost circular, since we define $fib$ in terms of itself. But it is a good definition, because at each step one *recurs* to smaller values. (Note that we read the equations from left to right, rewriting the left-hand side by the right-hand side.) The recursion will terminate when we reach $fib(0)$ and $fib(1)$. (Among the three cases that make up the definition, the first two are called the *base cases* while $fib(n+2) = fib(n) + fib(n+1)$ is called the *inductive case*.)

**Activity:** Compute $fib(6)$ by writing out a sequence of mathematical equations, replacing the $\ldots$ below.
\begin{align}
fib(6) & = fib(4) + fib(5)\\
& = \ldots \\
& = 8
\end{align}

Each step should correspond to either the application of one of the three defining equations of $fib$ or to one of the usual rules of mathematics for addition. [Hint: My computation has 37 steps.]

Why do I want you to write out the complete computation?
- To show you that the equational style of computation you learned in high-school extends to more complicated situations.
- The fact that this gets boring and tedious will make you think about how to mechanise this.
- This example illustrates well the technique known as [term-rewrting](https://en.wikipedia.org/wiki/Rewriting), which is the simplest and most important model universal model of computation.
- One advantage of term-rewriting is that we do not remember any "state": Each term in the chain of equations contains all that is needed to continue the computation to the end.
- A disadvantage is that in most steps we find ourselves copying terms that do not change.

The last point can easily be addressed. As it happens so often, thinking about how to get rid of the boring parts reveals interesting structure:

**Activity:** Draw the computation above in tree form by completing the figure below.

                        fib(6)
                          |
                          +
                         / \
                   fib(4)   fib(5)
                     |        |
                     +        +
                    / \      / \
                    ...      ...


Note that, as opposed to the equational reasoning, `fib(b)` only appears once in the tree now. On the other hand, the computation now proceeds by going up and down the tree in a particular fashion that is more intricate (it is known as [depth-first traversal](https://en.wikipedia.org/wiki/Depth-first_search)).
## Recursion in Python

Typically, modern programming languages do support writing recursive definitions.

	def fib(n):
	    if n==0:
	        return 0
	    elif n==1:
	        return 1
	    else:
	        return fib(n-2)+fib(n-1)

    print(fib(6))
    
**Important:** When the Python interpreter encounter the line `def fib(n):` it will **not** execute the function `fib`. It will just learn the definition of `fib`. Only when the Python interpreter processes the line `print(fib(6))`, the `fib(n)` will be called and executed, with the value `n` being `6`. 

**Activity:** Download and run [recursive_fib.py](https://github.com/alexhkurz/introduction-to-programming/blob/master/src/recursive_fib.py). Insert print-statements in various places in the program to help you track the execution for small values of `n`.

While the program above illustrates how recursion works in Python, it also highlights that Python does not have all the features that are needed to implement the mathematical definition in an elegant way. 

We will therefore also look quickly at a more mathematical programming language.

## Recursion in Haskell

In Haskell, the following is a program.

	fib 0 = 0
	fib 1 = 1
	fib n = fib (n-2) + fib (n-1)
    
Haskell is quite close to mathematical practice in many ways. One of the main differences are the conventions of how to place parentheses. For example, where in maths we would write $fib(n)$, in Haskell we can simply write `fib n`. 

**Activity:** Install the [Haskell platform](https://www.haskell.org/platform/). Download [fib.hs](https://github.com/alexhkurz/introduction-to-programming/blob/master/src/fib.hs). Run the program as follows.

    ghci
    :load fib.hs
    fib 5

## Homework

Write recursive programs in Python and Haskell to compute the value of $f(n)$ where $f$ is the any of the sequences of the [previous homework](https://hackmd.io/@alexhkurz/H1o4Mcr6L#Homework). I reproduce them here for convenience.


- $1, 2, 6, 24, 120,\ldots$
- $0,1,3,7,15,31, \ldots$
- $0,1,2,5,12,29,70, 169, \ldots$ 

We also had

- $0,1,3,6,10,15,\ldots$
- $0,1,5,14,30,55,\ldots$



## Further Reading

- [GeekforGeeks: Program for Fibonacci numbers](https://www.geeksforgeeks.org/program-for-nth-fibonacci-number/)
- [Haskell Wiki: The Fibonacci sequence](https://wiki.haskell.org/The_Fibonacci_sequence)
- [Full Computation of $fib(6)$](https://hackmd.io/@alexhkurz/HJiulVg0U)





