【问题标题】:Calling functions with different numbers of arguments in Rust macros在 Rust 宏中调用具有不同数量参数的函数
【发布时间】:2018-04-24 18:25:53
【问题描述】:

我需要一个可以调用具有不同数量参数的函数的宏,或者一个可以从其(重复)参数生成有效参数列表的宏。

我可以明确地提供有关宏参数数量的信息,但我不知道如何为函数生成参数列表 - 我总是偶然发现宏返回表达式而不是令牌树。

我做了以下playground example

macro_rules! call (
    ($f: expr, $($params:tt)*) => {
        $f(make_params!($($params:tt)*))
    };
);

macro_rules! make_params {
    () => {};
    (I $($params: tt)*) => {
        1, make_params!($($params:tt)*)
    };
}


fn foo(a: i32, b: i32, c: i32) {
    println!("foo: {} {} {}", a, b, c);
}

fn bar(a: i32, b: i32) {
    println!("bar: {} {}", a, b);
}

fn main() {
    call!(foo, I I I);
    call!(bar, I I);
}

编译器抱怨如下:

error: macro expansion ignores token `,` and any following
  --> src/main.rs:10:10
   |
10 |         1, make_params!($($params:tt)*)
   |          ^
   |
note: caused by the macro expansion here; the usage of `make_params!` is likely invalid in expression context
  --> src/main.rs:3:12
   |
3  |         $f(make_params!($($params:tt)*))
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...

如何将make_params! 的返回视为令牌流(或其他)而不是表达式?

我的真实用例比这个玩具示例要复杂一些。我的函数有多种参数类型,它们以不同的方式构造。就我而言,只制作宏 call1call2!、... 似乎不是一个好的解决方案,因为我需要 call_IIOOIcall_IIIO 等类似的东西。

【问题讨论】:

  • 宏必须扩展为有效的 AST 元素。 1, foo 不是有效的 AST 元素。
  • @mcarton 谢谢!哦,好吧......所以没有直接的方法来构造参数列表,你看到其他解决方案了吗?

标签: macros rust


【解决方案1】:

您需要在执行过程中逐步构建函数调用,最后只一次发出它:

macro_rules! call (
    ($f: expr, $($params:tt)*) => {
        make_call!($f, () $($params)*)
    };
);

macro_rules! make_call {
    ($f: expr, ($($args:tt)*)) => { $f($($args)*) };
    ($f: expr, () I $($params:tt)*) => {
        make_call!($f, (1) $($params)*)
    };
    ($f: expr, ($($args:tt)*) I $($params:tt)*) => {
        make_call!($f, ($($args)*, 1) $($params)*)
    };
}

playground

【讨论】:

  • 我看到这使用了一个累加器来构造参数列表。我想知道那个方向的东西,但不知道该怎么做。这或多或少正是我所需要的——谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-15
相关资源
最近更新 更多