1 Recursion
A recursive function is defined in terms of base cases and recursive steps.
In a base case, we compute the result immediately given the inputs to the function call.
In a recursive step, we compute the result with the help of one or more recursive calls to this same function, but with the inputs somehow reduced in size or complexity, closer to a base case.
1.1 Direct recursive implementation
1.2 Helper Method
In some cases, it’s useful to require a stronger (or different) specification for the recursive steps, to make the recursive decomposition simpler or more elegant.
Don’t expose the helperk method to your clients.
1.3 Choosing the Right Recursive Subproblem
2 Reentrant Code
Recursion – a method calling itself – is a special case of a general phenomenon in programming called reentrancy .
Reentrant code keeps its state entirely in parameters and local variables, and doesn’t use static variables or global variables, and doesn’t share aliases to mutable objects with other parts of the program, or other calls to itself.
It’s good to design your code to be reentrant as much as possible. Reentrant code is safer from bugs and can be used in more situations, like concurrency, callbacks, or mutual recursion.
3 When to Use Recursion Rather Than Iteration
The problem is naturally recursive (e.g. Fibonacci).
The data is naturally recursive (e.g. filesystem).
Another reason to use recursion is to take more advantage of immutability.
4 Common Mistakes in Recursive Implementations
The base case is missing entirely, or the problem needs more than one base case but not all the base cases are covered.
The recursive step doesn’t reduce to a smaller subproblem, so the recursion doesn’t converge.
Reference
[1] 6.005 — Software Construction on MIT OpenCourseWare | OCW 6.005 Homepage at https://ocw.mit.edu/ans7870/6/6.005/s16/