# Simple Macro with Recursion: Recursion limit hit directly

I've been following the book: Push-down Accumulation.

One macro in the book is defined as:

``````macro_rules! init_array {
(@accum (0, \$_e:expr) -> (\$(\$body:tt)*))
=> {init_array!(@as_expr [\$(\$body)*])};
(@accum (1, \$e:expr) -> (\$(\$body:tt)*))
=> {init_array!(@accum (0, \$e) -> (\$(\$body)* \$e,))};
(@accum (2, \$e:expr) -> (\$(\$body:tt)*))
=> {init_array!(@accum (1, \$e) -> (\$(\$body)* \$e,))};
(@accum (3, \$e:expr) -> (\$(\$body:tt)*))
=> {init_array!(@accum (2, \$e) -> (\$(\$body)* \$e,))};
(@as_expr \$e:expr) => {\$e};
[\$e:expr; \$n:tt] => {
{
let e = \$e;
init_array!(@accum (\$n, e.clone()) -> ())
}
};
}
``````

What I don't understand is why the macro cannot be defined as recursion. I tested writing it recursion style but hit the recursion limit directly (which in my opinion shouldn't be so) with the following code ` let array = init_array![String::from("Hello"); 3]`.

Here is the recursion example:

``````macro_rules! init_array {
(@accum (0, \$_e:expr) -> (\$(\$body:tt)*)) => {
init_array!(@as_expr [\$(\$body)*])
};
(@accum (\$n:expr, \$e:expr) -> (\$(\$body:tt)*)) => {
{
let _n = \$n - 1;
init_array!(@accum (_n, \$e) -> (\$(\$body)* \$e,))
}
};
(@as_expr \$e:expr) => {\$e};
[\$e:expr; \$n:tt] => {
{
let e = \$e;
init_array!(@accum (\$n, e) -> ())
}
};
}
``````

Why is this?

`_n - 1` isn't folded and never matches `0`, only `3 - 1` then `3 - 1 - 1` etc..

Even if it would, the moment you captured `\$n` as `expr`, it cannot be decomposed anymore and will never match `0`.

When forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type. The second macro can't use literal tokens to match the fragments in the matcher, only a fragment specifier of the same type. The `ident` , `lifetime` , and `tt` fragment types are an exception, and can be matched by literal tokens.

So you always hit the second arm and never the first arm, an infinite recursion.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.