Recursion
A function may call itself, or form a cycle with other functions.
Recursive types are allowed (replies: List<Comment>), and recursion is
the only way to walk them:
function reply_count(comment: Comment) -> ReplyTotal { var mut count: ReplyTotal = 0 for reply in comment.replies { count = ReplyTotal(count + 1 + reply_count(reply)) } return count}
Only functions may recurse. An action or query in a cycle of calls is an
error (effect.recursive_action).
How deep recursion can go is limited while the app runs, and going past the limit ends in a defined fault rather than a crash. The limits are the same in the interpreter and in a compiled build, on every target:
- A thousand frames, the test's own or the route's action's among them.
- Four hundred inline functions running at once, one inside another's body through the functions it calls.
Past either, the call or operation that would go deeper is the
recursion_limit fault, at its place in the code. That holds in
jadpo test and jadpo dev as in a deployable, a compiled build of your
app. So reply_count above walks a thread a thousand replies deep, and
the same walk written as list.map(comment.replies, reply -> ...) four
hundred.
Inline functions have the lower limit because compiled code runs each one inside its operation, several of the runtime's frames deep. On Workers those frames use V8's own stack, about a megabyte that nothing in the module can grow.
The stacks behind the limits:
- A native deployable's threads have the same stack as
jadpo test's, 64 MiB. - A Workers module is linked with 8 MiB of its own stack, which a thousand
frames of a large function fit. In a module, a callable entered with less
than 256 KiB of it left is also the
recursion_limitfault, so an even larger frame stops there rather than writing past the stack's end.
Markdown for agents: /docs/recursion.md.Built from Jadpo main at a707efb.