# Question on mutual recursion

**URL:** <https://discuss.ocaml.org/t/question-on-mutual-recursion/15631>\
**Category:** Learning\
**Created:** [November 17, 2024, 7:45pm UTC](https://discuss.ocaml.org/t/question-on-mutual-recursion/15631 "2024-11-17T19:45:41Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![user1](https://avatars.discourse-cdn.com/v4/letter/u/5daacb/32.png) [@user1](https://discuss.ocaml.org/u/user1)\
**Post date:** [November 17, 2024, 7:45pm UTC](https://discuss.ocaml.org/t/question-on-mutual-recursion/15631/1 "2024-11-17T19:45:41Z")

</div>

While writing some convoluted function on a custom recursive type, I ended up with the following pattern:

```auto
let rec f n =
  if n < 0 then n else
    let g n = f (n - 1) in
    g (n - 1)

```

which I figure has the same behavior as the mutual recursion

```auto

let rec f n =
  if n < 0 then n else
    g (n - 1)
and g n = f (n - 1)

```

What are the differences of these two (knowing that I do not care about `g` being available for later) ? For instance, in terms of performance, allocation. Is it different if the calls to `f` and `g` are not tail-calls ? In the first case, a non-recursive function `g` is “created” for each call to `f`, so it may be worse for allocation ? But maybe mutual recursion is worse ?

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [November 17, 2024, 8:30pm UTC](https://discuss.ocaml.org/t/question-on-mutual-recursion/15631/2 "2024-11-17T20:30:51Z")

</div>

> [@user1](#):
>
> In the first case, a non-recursive function `g` is “created” for each call to `f`, so it may be worse for allocation ?

Actually, no closure is created for `g` because its free variables (namely, `f`) are global, hence constant. So there isn’t any allocation at all. The code generated in both cases is pretty much the same, except that the compiler more readily inlines the first `g` because it is not exposed outside `f`.

Incidentally, you can compare the generated code for each case by passing `-dlambda` to the compiler (for the Lambda intermediate form, used for bytecode generation) and/or `-dcmm` (for the C-- intermediate form, used for native code generation).

Cheers,  
Nicolas
