liveBook · Manning

Tail-call optimization

As explained in Functional Programming in JavaScript

A compiler optimization that reuses the current call frame for a function call in tail position instead of creating a new stack frame.

Tail-call optimization (TCO) makes certain recursive programs use the stack more like a loop. When the final operation is another function call, the runtime can discard the current frame instead of stacking a new one. section 7.4

A recursive call can use TCO when:

  • The recursive call is in tail position: it is the last operation, with no multiplication, addition, or other work remaining afterward. section 7.4
  • The function passes necessary state through arguments, often using an accumulator. section 7.4
  • The compiler or runtime reuses a single execution frame rather than allowing recursive frames to accumulate. section 7.4

Accumulator-based factorial

const factorial = (n, current = 1) => (n === 1) ? current : factorial(n - 1, n * current); Each call carries the result accumulated so far. The recursive call is the final action, so evaluating factorial(4) can proceed through successive argument values instead of building a pyramid of pending multiplications. section 7.4

Figure 7.9. A detailed view of tail-recursive factorial(4) evaluation. As you can see, the function uses a single frame. TCO is in charge of throwing the current function frame to give way for a new one, as if factorial was being evaluated in a loop.

Shows tail-recursive factorial evaluation using a single reusable frame, making the stack benefit visible. section 7.4

How Functional Programming in JavaScript covers it

How deep it goes
Explains tail position, accumulated arguments, and single-frame reuse, but does not develop broader compiler behavior.
Examples
Uses factorial evaluation and accumulator-based array summation to contrast ordinary and tail-recursive forms.
What it assumes
Assumes basic recursion and stack behavior while introducing tail position and accumulator passing.
What you can do after
Apply it by converting recursive factorial or summation functions into accumulator-based tail-recursive forms.
How it connects
Connects recursion with loops, memoization, compiler optimization, and stack usage.

Also explained in

Compare how 3 books explain tail-call optimization →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in JavaScript. The section links point to the parts of the book it draws on.