如何在引用中两次使用迭代器!宏?

我正在尝试从proc 宏研讨会实现构建器模式我正在创建一个 proc 宏,它解析一个结构,提取其name,field_namesfield_types. 它应该重现结构本身,并创建一个具有相同field_names但具有可选类型的构建器结构。

我的问题是,field_name并且field_type是迭代器,我必须使用两次才能从一个结构中创建两个结构。

这是我的源代码树

.
??? Cargo.lock
??? Cargo.toml
??? builder-derive
?   ??? Cargo.toml
?   ??? src
?       ??? lib.rs
??? src
    ??? main.rs

./cargo.toml

[package]
name = "proc-macro-question"
version = "0.1.0"
authors = ["ropottnik <ropottnik@example.com>"]
edition = "2018"

[dependencies]
builder-derive = { path = "./builder-derive" }

./main.rs

[package]
name = "proc-macro-question"
version = "0.1.0"
authors = ["ropottnik <ropottnik@example.com>"]
edition = "2018"

[dependencies]
builder-derive = { path = "./builder-derive" }

./builder-derive/cargo.toml

[package]
name = "builder-derive"
version = "0.1.0"
authors = ["ropottnik <ropottnik@example.com>"]
edition = "2018"

[lib]
proc-macro = true

[dev-dependencies]
trybuild = { version = "1.0", features = ["diff"] }

[dependencies]
syn = { version= "1.0", features = ["extra-traits"] }
quote = "1.0"

./builder-derive/src/lib.rs

#[derive(Builder)]
struct SomeStruct {
    some_field: i32,
}

fn main() {
    println!("Hello, world!");
}

$ cargo run 输出

[package]
name = "builder-derive"
version = "0.1.0"
authors = ["ropottnik <ropottnik@example.com>"]
edition = "2018"

[lib]
proc-macro = true

[dev-dependencies]
trybuild = { version = "1.0", features = ["diff"] }

[dependencies]
syn = { version= "1.0", features = ["extra-traits"] }
quote = "1.0"

我想我可以为每次使用创建一个迭代器,但这对我来说似乎是不可能的;-)

回答

迭代器只能使用零次或一次,不能多次使用;这是标准的 Rust,不涉及quote!宏:

fn example() {
    let nums = std::iter::empty::<i32>();
    for _ in nums {}
    for _ in nums {}
}
error[E0382]: use of moved value: `nums`
   --> src/lib.rs:4:14
    |
2   |     let nums = std::iter::empty::<i32>();
    |         ---- move occurs because `nums` has type `std::iter::Empty<i32>`, which does not implement the `Copy` trait
3   |     for _ in nums {}
    |              ----
    |              |
    |              `nums` moved due to this implicit call to `.into_iter()`
    |              help: consider borrowing to avoid moving into the for loop: `&nums`
4   |     for _ in nums {}
    |              ^^^^ value used here after move
    |
note: this function consumes the receiver `self` by taking ownership of it, which moves `nums`

即使您通过可变引用获取迭代器,迭代一次也会耗尽它,第二次使用时不会留下任何值。

您将需要克隆迭代器:

use quote::quote; // 1.0.8

fn example() {
    let nums = std::iter::empty::<i32>();
    let nums2 = nums.clone();

    quote! {
        #(#nums)*
        #(#nums2)*
    };
}

您还可以将迭代器收集到 a 中Vec并对其进行多次迭代:

use quote::quote; // 1.0.8

fn example() {
    let nums = std::iter::empty();
    let nums: Vec<i32> = nums.collect();
    
    quote! {
        #(#nums)*
        #(#nums)*
    };
}


以上是如何在引用中两次使用迭代器!宏?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>