Lists and Recursion
Recursion  functions calling themselves

We have seen functions that call other functions

Functions can also call themselves  this allows repeated computations
to take places, which is the real power of any programming language 
doing the same thing over and over

Example: Multiply defined by using repeated addition, then defined as N*M
= N + (N1)*M

Note that * appears on both sides  this is a recursive definition 
its uses itself to define itself

The problem is when do you stop? For the multiplication example,
we stop when (N1) is 0

So, the recursive definition of multiplication is really
N*M is if N=1 then M else N + (N1)*M

Hint: that's how you would write it in ML, too!

The stopping point is the base case (here, where N=1), the call
to itself is the recursive case

The recursive case must always make sure the problem is getting smaller
 i.e., approaching the base case.
Lists  a new data structure

ML has a data type called lists, which is exactly what it sounds
like, a list of values

Unlike a tuple, a list has to have values of all the same type. You can
have a list of real numbers, a list of strings, but not a list of reals
and strings mixed together

Also unlike a tuple, which is a fixed length, a list can be as long or
as short as it needs to be

A list is formed by using square brackets with element values separated
by commas

[ 1, 5, 3, 1, 7, 2, 3 ] is an int list

Lists are very powerful. Now we can really start programming! We have ways
to store as much data as we have (with lists), and a way to do repeated
computation (with recursion)

Until now, our functions were basically like calculators

Operations on lists  hd(List) gives you the first element
of the list, and tl(List) gives you all the rest of the
list except the first element, and null(List) returns true
if a list is empty, and false otherwise.
The :: or the cons operator lets you construct bigger lists from
smaller ones.

That's really all you need to process lists, but there's also length(List),
which returns an integer that is the length of the list, and List.nth(List,N:int)
which returns the Nth element of a list, where the first element
is at 0
some function definitions.