Recursion
Also known as: recursion recursive call itself stack overflow factorial fibonacci
● Beginner4 minBefore this: FunctionsSpec 3.8
A function may call itself, as long as each call gets closer to a case that stops.
fn factorial(n: Int) -> Int {
if n <= 1 { 1 } else { n * factorial(n - 1) }
}
fn main() {
print(factorial(5))
print(factorial(20))
}The program ran and printed:
kavach run factorial.kav
1202432902008176640000
factorial(5) is 5 * factorial(4), and so on down to factorial(1), which is just 1: the case that stops.
Too deep
Each call waits for the next, and the waiting calls take room. Far too many stop the program, cleanly:
fn depth(n: Int) -> Int {
if n == 0 { 0 } else { 1 + depth(n - 1) }
}
fn main() {
print(depth(1000))
print(depth(100_000_000))
}The program ran, then stopped with a panic:
kavach run deep.kav
1000panic: stack overflow: calls are nested too deeply (spec 3.8)
How deep it can go
Each call that waits keeps its parameters and values on the stack, a block of memory that holds the calls still running. How many fit depends on where the program runs:
| Where it runs | Stack | Deepest recursion |
|---|---|---|
| kavach run (the interpreter) | 512 MB, of which it keeps 32 MB in hand to report the overflow | tens of thousands of small calls, about 50,000 in a release build of kavach: measured as calls use the stack, not counted, so bigger calls go less deep |
| Native code: kavach build, kavach run --native | 512 MB for the program | about 13 million calls of a small function like depth above (measured with kavach run --native), about 36 bytes each; fewer when each call holds more values |
| Each task, from spawn | 512 MB each, of address space: memory is used only as calls need it | the same as native code |
| A library called from another language (kavach build --lib) | 256 KB below the caller | a few thousand small calls: the caller's own stack is unknown, often 1 MB, so a deep recursion stops well before it |
| A gpu fn | none | no recursion at all: it is a compile error |
Past the limit, the program stops with the panic above: never a crash or corrupted memory.
For a long repetition, a for or while loop is the right tool.
What Kavach does for you
Adding recursion becomes a loop
A function that calls itself to add up a result runs as a loop, as fast as one. Nothing you can see changes: a recursion too deep for the stack still stops with the same message.