General recursion.
The English word recursion is derived from a Late Latin word meaning to run back. Something is recursive, in the general sense of the word, whenever a part of the thing is a copy of the entire thing. As with the curves in the image above, at each step of examining it, either more closely or more broadly, the same form is observed.
Recursive computing algorithms.
In computer programming, a recursive function is one which, in some cases, calls itself as part of its process. To be a useful function it is important that there be at least one case where it does not call itself and that each level of recursion (each call to itself) move closer to this case. If both of these conditions are not met the function may became stuck in a state of infinite recursion. The program will hang, never reaching the next step it is meant to accomplish.
The cases where recursion depth does not increase are refered to as the base cases. For example, in the following CSC148 example function for finding the sum of all numbers in a set of nested lists the base case is when the item being examined is a number rather than a list.
def sum_list(L: list) -> float:
'''Return sum of the numbers in L.
L - a possibly nested list of numbers. L, and all sublists, are non-empty
>>> sum_list([1, 2, 3])
6
>>> sum_list([1, [2, 3, [4]], 5])
15
'''
return sum([sum_list(x) if isinstance(x, list) else x for x in L])
A draw back of recursion.
The main problem I am aware of with use of recursion in computer programming is memory usage. Each time a function calls itself a new frame has to be added to the stack containing new instances of every object used by the function. This can reduce performance of other programs or even crash the computer if allowed to continue for a very large number of levels of recursion. To prevent this Python, by default, only allows 1000 levels of recursion. This prevents the worst problems, but also places some limits on the usefulness of recursion.
Tail recursion.
The problem of recursion gobbling up memory can be fixed in some cases by using tail call optimization. A tail call recursion is when a function calls itself as the very last thing it does before returning. In this case, unlike a recursive call anywhere else in the function, any information in the stack frame that isn't being passed to the new instance of the function can be safely discarded. If a language supports tail recursion optimization it will identify these situations and clean up the completed function call before beginning the next one. This keeps the stack from growing at all, no matter how many times a tail recursive function call itself.
As interesting as this is, Python does not have tail recursion optimization and is very unlikely to support it any time soon. Working in Python, very deep recursion may need to be either rewritten as iteration or manually tail call optimized using helper functions.
The last visible dog.
Talking about recursion reminds me of the film The Mouse and His Child (based on the excellent and bizarre book of the same name). In this story some characters ascribe a mystical significance to the "last visible dog" in a recursive logo image printed on cans of a specific brand of dog food.
Image made from CC images by Elijah Porter and Kevin Dooley.


