Basic example, with pure functions:

```
fn main ()
{
type Int = u32;
fn is_even (n: Int) -> bool
{
trace_fn! { "is_even({})", n =>
n == 0 || is_odd(n - 1) // FUNCTION BODY
}
}
fn is_odd (n: Int) -> bool
{
trace_fn! { "is_odd({})", n =>
n != 0 && is_even(n - 1) // FUNCTION BODY
}
}
dbg!(is_even(5));
}
```

prints

```
is_even(5)?
| is_odd(4)?
| | is_even(3)?
| | | is_odd(2)?
| | | | is_even(1)?
| | | | | is_odd(0)?
| | | | | +-> false
| | | | +-> false
| | | +-> false
| | +-> false
| +-> false
+-> false
[src/main.rs:47] is_even(5) = false
```

Regarding an example with closures, this, as @OptimisticPeach said, wonâ€™t be possible in general, due to it requiring two â€śobjectsâ€ť that refer to each other, thus implying self-referentiability which, as we know, is a problematic pattern in Rust.

However, this can be avoided by using `static`

closures (it requires naming the type of a closure, which in stable can only be done with environment-less closures by coercing them to `fn()`

pointers), since a `static`

is not part of a closureâ€™s environment:

```
#[allow(non_upper_case_globals)]
fn main ()
{
type Int = u32;
static is_even: fn(Int) -> bool = |n| {
trace_fn! { "is_even({})", n =>
n == 0 || is_odd(n - 1)
}
};
static is_odd: fn(Int) -> bool = |n| {
trace_fn! { "is_odd({})", n =>
n != 0 && is_even(n - 1)
}
};
dbg!(is_even(14));
}
```

Lastly, and this one is the most interesting, is that since a closure is just an object with a method, we can avoid the self-referentiability issue by having *one â€śobjectâ€ť with two methods* (we lose some sugar but it remains fine).

(In my example, `is_even`

and `is_odd`

will be sharing a reference to an `out_stream`

:

```
type Int = u32;
/// Our "double closure" trait
trait EvenTheOdds {
fn is_even (&mut self, n: Int) -> bool;
fn is_odd (&mut self, n: Int) -> bool;
}
struct TraceFn<W : Write> {
out_stream: W,
}
impl<W : Write> EvenTheOdds for TraceFn<W> {
fn is_even (&mut self, n: Int) -> bool
{
trace_fn! { using &mut self.out_stream, "is_even({})", n =>
n == 0 || self.is_odd(n - 1)
}
}
fn is_odd (&mut self, n: Int) -> bool
{
trace_fn! { using &mut self.out_stream, "is_odd({})", n =>
n != 0 && self.is_even(n - 1)
}
}
}
fn main ()
{
let mut stderr_tracer = TraceFn { out_stream: io::stderr() };
dbg!(stderr_tracer.is_even(14));
}
```