Tail carries the answer
When the recursive call is the last action and the result is passed down as an argument, no work waits on the return.
A simple recursion walks down to the base case, then the answers come back up. Where you do the work, on the way down or on the way back, changes the result.
About 2 min of reading
Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.
Control the order of work in a recursion.
Join rising digits.
Before you run it, say out loud what it will print. Then open the answer.
Join falling digits.
Before you run it, say out loud what it will print. Then open the answer.
Sum a list on return.
Before you run it, say out loud what it will print. Then open the answer.
Tail sum with acc.
Before you run it, say out loud what it will print. Then open the answer.
Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.
Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.
When the recursive call is the last action and the result is passed down as an argument, no work waits on the return.
Doing work before the call runs on the way down; doing it after runs on the way back. The same recursion gives different orders.
def up(n):
if n == 0:
return ""
return up(n - 1) + str(n)
print(up(3))
The call happens first, then the text. So the numbers join in rising order.
def down(n):
if n == 0:
return ""
return str(n) + down(n - 1)
print(down(3))
The text is added before the call. The numbers join in falling order.
def show(n):
if n == 0:
return
print(n)
show(n - 1)
show(3)
Printing before the call shows 3, 2, 1. The calls still nest, but nothing is returned.
def show(n):
if n == 0:
return
show(n - 1)
print(n)
show(3)
Printing after the call shows 1, 2, 3. The print runs as the calls return.
def s(a):
if not a:
return 0
return a[0] + s(a[1:])
print(s([1, 2, 3, 4]))
Each frame adds its head after the smaller sum returns. The total builds upward.
def c(n):
if n <= 0:
return 0
return 1 + c(n - 1)
print(c(5))
One call per step. The depth of nesting equals the starting number.
def t(n, acc):
if n == 0:
return acc
return t(n - 1, acc + n)
print(t(4, 0))
The answer is carried in acc and the call is last. Nothing is added after it returns.
def t(n, acc):
if n == 0:
return acc
return t(n - 1, acc + n)
print(t(10, 0))
Passing the running total down means no work waits on the return. That is the tail shape.
Each one is defined here on this site. Open the entry for the full definition and the other words it points at.