Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Functions  ›  Lesson

Recursion — Functions that Call Themselves

Recursion 12 minA recursive function solves a problem by calling itself on a smaller version of the same problem, and it needs a base case that stops the calls.

Recursion — Functions that Call Themselves

The garden is laid out in beds, some beds are split into sections, and some sections into plots. Totalling a structure like that, where each part can contain smaller parts of the same shape, is awkward with loops and natural with recursion: a function that solves a problem by calling itself on a smaller piece of it.

The rule

Every recursive function needs a base case and a smaller step towards it.

  • The base case is a version of the problem so small that the answer is obvious, so the function returns it directly.
  • The recursive step handles one small piece itself and hands the rest to a call of the same function, on a smaller input.
total_kg <- function(x) {
  if (length(x) == 0) return(0)   # base case: nothing left to add
  x[1] + total_kg(x[-1])          # first plot + total of the rest
}

total_kg(c(12.5, 8, 15, 3.5, 6))  # 45

Each call peels off the first weight, so the input shrinks by one element every time and must eventually reach the empty vector, the base case.

The classic example is the factorial, where 5! means 5 × 4 × 3 × 2 × 1:

fact <- function(n) {
  if (n <= 1) return(1)   # base case
  n * fact(n - 1)         # smaller step
}
fact(5)   # 120

Where recursion earns its place is nested data: a list of beds, each a list of sections, each a list of plots. A recursive function says "if this is a plain number, return it; if it is a list, total each item with this same function and add the results", and it handles any depth without knowing it in advance.

Where it does not is plain vectors. sum(kg) beats total_kg(kg) in speed and clarity. Every call also takes up memory until it finishes, so very deep recursion (thousands of levels) stops with an error. Forget the base case, or make a step that does not shrink the input, and you hit that limit almost at once: the calls never end, so R stops them with an error once they nest too deeply.

The shortcut

Trust the smaller call. When writing, assume total_kg(x[-1]) already works for the rest, and only ask two questions: is the base case right, and does each step shrink the input? When tracing, write the calls going down, then complete the sums coming back up.

Tracing fact(4)Step 1 of 4
  1. Going down

    fact(4) needs 4 * fact(3).

Drills

Answer fast — trust the rule.

quick drill

What is fact(5)?

quick drill

What does total_kg(numeric(0)) return?

quick drill

How many times is total_kg called, in total, for a 5-element vector?

quick drill

With fib <- function(n) if (n <= 2) 1 else fib(n - 1) + fib(n - 2), what is fib(6)?

quick drill

What happens if you delete the base case line from fact?

Remember

  • Every recursive function needs a base case and a smaller step towards it.
  • Shortcut: trust the smaller call; trace down to the base case, then build the answer back up.
  • Trap: a missing base case, and using recursion where sum() or a loop is simpler.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainTrust the smaller call

Explain how total_kg(c(8, 15, 3.5)) works for the recursive total_kg function from this lesson, listing each call and how the answer is built on the way back. Then say what would happen without the base case.