How it works
The explanation, with examples you can run.
The two parts
Every correct recursive function has a base case that it answers without recursing and a recursive case that moves strictly towards it. Summing a nested list is a natural fit, because the data is itself recursive: a list contains numbers or more lists.
Press Run to see what your code prints, in order.
Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.
The iterative version does the same work in a different order: instead of the runtime remembering "I'm halfway through this list", the explicit stack holds the items not yet visited. Trees, file-system walks, JSON processing, parsers and divide-and-conquer sorts like merge sort and quicksort are all naturally written this way.
The cost: stack depth
Each call needs a stack frame for its arguments, locals and return address, and the call stack is small, under a megabyte in Node 22 (V8's --stack-size defaults to 864 KB there), far less than the heap. Python sets a recursion limit instead: sys.getrecursionlimit() returns 1000 by default, and exceeding it raises RecursionError. Recursion depth follows the shape of the input, so code that works on every test can overflow on one deeply nested document:
Press Run to see what your code prints, in order.
Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.
Some languages guarantee tail call elimination: if the recursive call is the very last thing a function does, the runtime reuses the current frame. ES2015 actually specified proper tail calls for strict-mode JavaScript, but V8 (Chrome and Node) has them switched off, and CPython deliberately doesn't do it either, so in both languages deep recursion overflows no matter how you write it.
Choosing
Write the recursive version first when the problem is recursive: it is usually shorter and easier to get right. Switch to an explicit stack when depth depends on untrusted or unbounded input, such as user-supplied JSON, long linked structures, or graph searches over millions of nodes. Using a queue instead of a stack in the same loop changes depth-first order into breadth-first order, which is the subject of the graphs topic.
Recursion can also repeat work. A naive recursive Fibonacci recomputes the same values exponentially many times; caching the results, memoisation, fixes that and leads straight into dynamic programming.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.