rust - 为什么以下宏在被调用时会期望使用分号?

标签 rust rust-macros

我正在尝试编写一个宏,以根据构建功能在人造丝的par_iter和std的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
虽然我对第一个错误一无所知,但我很好奇为什么要使用;-如何在表达式上下文中使其有效?

最佳答案

本质上可以归结为,不允许在这样的表达式中包含attributes,例如以下无效:

b_slice.iter()
    #[cfg(not(feature = "threaded"))]
    .map(|x| x)
    .collect();
要解决此问题,您可以将它们分配给一个临时变量,如下所示:
注意双{{}},它们产生block,使得最终表达式是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()
    }
}

关于rust - 为什么以下宏在被调用时会期望使用分号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65572271/

相关文章:

vector - 如何为向量的迭代器元素添加 Into 的类型注释?

rust - 在迭代器上创建方法,在 Rust 中返回迭代器

rust - 为什么 `ToString` 项的迭代器要求它们也为 `Display`?

rust - 我可以重写这个宏规则吗!宏以一种与 rustfmt 一起工作的方式?

rust - 如何为特征的每个实现自动生成递增的数字标识符?

rust - 如何告诉 Cargo 使用 git 存储库作为间接依赖的来源而不是 crates.io?

rust - 在 Rust 中实现 vs 派生

rust - "expected identifier"创建宏时同时定义可变变量

debugging - 如何查看导致我的编译错误的扩展宏代码?

rust - 如何在 `quote!` 宏中的变量之后立即连接 token ?