macros - 在 Rust 宏中调用具有不同数量参数的函数
问题描述
我需要一个可以调用具有不同数量参数的函数的宏,或者一个可以从其(重复)参数生成有效参数列表的宏。
我可以明确地提供有关宏参数数量的信息,但我无法弄清楚如何为函数生成参数列表 - 我总是偶然发现宏返回表达式而不是令牌树。
我做了以下操场示例:
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!
视为令牌流(或此类)而不是表达式?
我的真实用例比这个玩具示例要复杂一些。我的函数有多种参数类型,它们以不同的方式构造。就我而言,仅制作宏call1
, call2!
, ... 似乎不是一个好的解决方案,因为我需要诸如call_IIOOI
,call_IIIO
等之类的东西。
解决方案
您需要在执行过程中逐步构建函数调用,最后只发出一次:
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)*)
};
}
推荐阅读
- node.js - 有没有办法列出目录 node.js 中所有文件的文件扩展名?
- c++ - 来自 C++ SDK 的 IF 语句措辞不正确
- python - 如何让我的项目在重新启动后记住变量/列表?
- javascript - 图像滑块需要额外单击 1 次才能重置。无法修复
- google-apps-script - 电子邮件通知中出现错误“异常:单元格引用超出范围”
- javascript - 如何设置在线服务器以不断执行我的 javascript 代码?
- xcode - Flutter运行和flutter pub sec报错| 颤振驱动程序
- google-cloud-functions - 由 Pub Sub 触发的 Cloud Function 未发布预期消息
- linux - 单个大文件上的 OverlayFS
- tailwind-css - 如何使用 Tailwindcss 创建一个真正的粘性页眉/页脚(即使滚动也会粘在底部)?