``` 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ``` ``` public static int numFives (double[] list) { int result = numFivesHelper (list, 0, 0); return result; } public static int numFivesHelper (double[] list, int i, int result) { if (i < list.length) { if (list[i] == 5) { result++; } result = numFivesHelper (list, i + 1, result); } return result; }```

For `[5,11,5,5]`, the call tree is

```call@3 ([5,11,5,5], 0)
call@4 ([11,5,5], 1)
call@5  ([5,5], 1)
call@6  ([5], 2)
call@7 ([], 3)
retn@7 ([], 3) : 3
retn@6  ([5], 2) : 3
retn@5  ([5,5], 1) : 3
retn@4 ([11,5,5], 1) : 3
retn@3 ([5,11,5,5], 0) : 3```

(Abbreviating `list` and `i` as single parameter showing `list[i..]`.)

Converted to a recursive function.

Note that we do not mutate i in the helper

Note that computation goes forwards. We forget the old values of i as we go forward.

This kind of recursion is called tail recursion: the recursive call is the last thing the function does before it returns.

There is a one-to-one correspondence between loops and tail-recursive functions. We can mechanically convert between these to forms. Compilers do it all the time.