如何递归采用宏的最后一个参数? [英] How to recursively take the last argument of a macro?

查看:83
本文介绍了如何递归采用宏的最后一个参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用一个简单的递归宏,如下面的示例,它的共同点是第一个参数,然后遍历其余参数.

Using a simple recursive macro like the example below, its common to take the first argument, then glob the rest.

macro_rules! count_tts {
    () => {0usize};
    ($_head:tt $($tail:tt)*) => {1usize + count_tts!($($tail)*)};
}

有没有一种方法可以递归地接受最后一个参数?

Is there a way to recursively take the last argument?

这使得可以:

  • 反向处理参数.
  • 考虑所有先前的参数(例如,将其计数为查看相关问题)

类似($($head:tt)* $tail:tt)的东西,但这不起作用.

Something like ($($head:tt)* $tail:tt) ... but this doesn't work.

推荐答案

宏解析器中没有回溯"功能,所以不能使用$($head:tt)* $tail:tt直接执行此操作.但是您可以自己反转.

There is no "backtracking" in the macro parser, so no you can't do this directly with $($head:tt)* $tail:tt. But you can do it by reversing it yourself.

macro_rules! concat_reverse {
    ([] $($reversed:tt)*) => { 
        concat!($(stringify!($reversed)),*)  // base case
    };
    ([$first:tt $($rest:tt)*] $($reversed:tt)*) => { 
        concat_reverse!([$($rest)*] $first $($reversed)*)  // recursion
    };
}

fn main() {
    println!("{}", concat_reverse!([e d c b a]))
    // output: abcde
}

宏跟踪如下:

   concat_reverse!([e d c b a])
== concat_reverse!([d c b a] e)
== concat_reverse!([c b a] d e)
== concat_reverse!([b a] c d e)
== concat_reverse!([a] b c d e)
== concat_reverse!([] a b c d e)
== concat!(stringify!(a), stringify!(b), stringify!(c), stringify!(d), stringify!(e))

您可以在递归阶段执行一些映射"和减少"操作(例如,用于计数).

You could do some "map" and "reduce" operation (e.g. for counting) in the recursion phase.

请注意,此方法会影响您的递归深度,您可能需要提高#![recursion_limit="..."].

Note that this method will eat your recursion depth, you may need to raise your #![recursion_limit="..."].

这篇关于如何递归采用宏的最后一个参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆