Understanding how recursive functions work

后端 未结 18 986
野性不改
野性不改 2020-11-22 07:08

As the title explains I have a very fundamental programming question which I have just not been able to grok yet. Filtering out all of the (extremely clever) \"In order to

18条回答
  •  青春惊慌失措
    2020-11-22 07:48

    I think the best way to understand recursive functions is realizing that they are made to process recursive data structures. But in your original function sumInts(a: Int, b: Int) that calculates recursively the sum of numbers from a to b, it seems not to be a recursive data structure... Let's try a slightly modified version sumInts(a: Int, n: Int) where n is how many numbers you'll add.

    Now, sumInts is recursive over n, a natural number. Still not a recursive data, right? Well, a natural number could be considered a recursive data structre using Peano axioms:

    enum Natural = {
        case Zero
        case Successor(Natural)
    }
    

    So, 0 = Zero, 1 = Succesor(Zero), 2 = Succesor(Succesor(Zero)), and so on.

    Once you have a a recursive data structure, you have the template for the function. For each non recursive case, you can calculate the value directly. For the recursive cases you assume that the recursive function is already working and use it to calculate the case, but deconstructing the argument. In the case of Natural, it means that instead of Succesor(n) we'll use n, or equivalently, instead of n we'll use n - 1.

    // sums n numbers beginning from a
    func sumInts(a: Int, n: Int) -> Int {
        if (n == 0) {
            // non recursive case
        } else {
            // recursive case. We use sumInts(..., n - 1)
        }
    }
    

    Now the recursive function is simpler to program. First, the base case, n=0. What should we return if we want to add no numbers? The answer is, of course 0.

    What about the recursive case? If we want to add n numbers beginning with a and we already have a working sumInts function that works for n-1? Well, we need to add a and then invoke sumInts with a + 1, so we end with:

    // sums n numbers beginning from a
    func sumInts(a: Int, n: Int) -> Int {
        if (n == 0) {
            return 0
        } else {
            return a + sumInts(a + 1, n - 1)
        }
    }
    

    The nice thing is that now you shouldn't need to think in the low level of recursion. You just need to verify that:

    • For the base cases of the recursive data, it calculates the answer without using recursion.
    • For the recursive cases of the recursive data, it calculates the answer using recursion over the destructured data.

提交回复
热议问题