Functional programming languages do not have variables, assignment or iteration. You can achieve the same effects using just lists and recursion.
There are two main sorts of recursion over lists. The first is called mapping: a function is applied to each element of a list, producing a new list in which each element has been transformed.
map fn [a,b,c] == [fn a, fn b, fn c]
The second main sort of recursion is called folding: a list is turned into a single value by joining pairs of elements together with a function and a start value.
foldr fn start [a,b .. c] == (fn a (fn b (.. (fn c start))))
(The function is called foldr as it folds the list up right-to-left. There is an analogous function called foldl which folds a list up left-to-right, but because of the way lists work, it is much slower and should be avoided if possible.)
map is defined in the standard list library for you:
/* map fn l: map function fn over list l */ map fn l = [], l == [] = fn (hd l) : map fn (tl l)
So, for example, you could use map like this:
map (add 2) [1..5] == [3,4,5,6,7,8]
foldr is defined in the standard list library for you:
/* foldr fn st l: fold up list l, right to * left with function fn and start value st */ foldr fn st l = st, l == [] = fn (hd l) (foldr fn st (tl l))
So, for example, you could use foldr like this:
foldr add 0 [1..5] == 15
(Mathematically, foldr is the more basic operation. You can write map in terms of foldr, but you can't write foldr in terms of map.)
Unconstrained recursion over lists can be very hard to understand, rather like goto in an imperative language. It's much better to use a combination of map and foldr if you possibly can.
The toolkit _list contains definitions of most of the standard list-processing functions. These are listed in Table 6.3. Check the source for detailed comments.