rust - 为什么以下宏在调用时需要分号?
问题描述
我正在尝试编写一个宏来根据构建功能在人造丝par_iter
和标准之间切换(可能领先于自己,因为我还没有读过很多关于宏的内容)。iter
在这里,宏似乎比函数好一点,因为函数可能需要一些相对复杂的类型才能使其工作;如果我想在与如何运行迭代器有关的构建功能中添加更多变体,那么将来宏可能会更加灵活。
#[macro_export]
macro_rules! par_iter {
($($tokens:tt)*) => {
#[cfg(feature = "threaded")]
$($tokens)*.par_iter()
#[cfg(not(feature = "threaded"))]
$($tokens)*.iter()
}
}
我看到以下错误:
error: macro expansion ignores token `b_slice` and any following
--> src/util.rs:28:8
|
28 | $($tokens)*.iter();
| ^^^^^^^^^
|
::: src/counting.rs:219:9
|
219 | par_iter!(b_slice).map(WordCount::from)
| ------------------- help: you might be missing a semicolon here: `;`
| |
| caused by the macro expansion here
|
= note: the usage of `par_iter!` is likely invalid in expression context
虽然我不知道第一个错误,但我很好奇为什么 a;
是预期的 - 我如何使它在表达式上下文中有效?
解决方案
这基本上归结为,您不允许在这样的表达式中具有属性,例如以下内容是无效的:
b_slice.iter()
#[cfg(not(feature = "threaded"))]
.map(|x| x)
.collect();
要解决此问题,您可以将它们分配给一个临时变量,如下所示:
请注意结果为block的 double {{
and ,这样最终的表达式就是 block 结果的值。}}
#[macro_export]
macro_rules! par_iter {
($($tokens:tt)*) => {{
#[cfg(feature = "threaded")]
let it = $($tokens)*.par_iter();
#[cfg(not(feature = "threaded"))]
let it = $($tokens)*.iter();
it
}};
}
或者,您也可以将其拆分为两个宏,如下所示:
#[cfg(feature = "threaded")]
#[macro_export]
macro_rules! par_iter {
($($tokens:tt)*) => {
$($tokens)*.par_iter()
}
}
#[cfg(not(feature = "threaded"))]
#[macro_export]
macro_rules! par_iter {
($($tokens:tt)*) => {
$($tokens)*.iter()
}
}
推荐阅读
- python - 使用numpy内存映射python提取文件
- curl - 我应该如何为 ftp 下载设置 curl 超时?
- c# - 需要将我的枚举插入 C# 中的组合框
- python - NLP - Python - 条件频率分布
- asp.net-mvc - ASP NET MVC 上一页
- php - 如何防止标题在 php mysqli 中重复
- list - 使用 Haskell 上的递归返回给定正整数的元组列表
- http - 即使在重新启动 IDE 后,FLUTTER 中的未定义名称“http”
- markdown - 摆脱 Sphinx 中的“重复标签”警告
- java - maven-shade-plugin 输出带有 shadedArtifactAttached 错误被安装覆盖