Rust 中的迭代器类型

Ste*_*art 5 rust

我正在学习 Rust 并遇到了问题。我有这个 MCVE:

fn main() {
    let mut line = String::new();
    std::io::stdin()
        .read_line(&mut line)
        .expect("Failed to read line");

    handle_tokens( line.split_ascii_whitespace() );
}

fn handle_tokens( mut it: std::str::SplitAsciiWhitespace ) {
    loop {
        match it.next() {
            None => return,
            Some(s) => println!("{}",s),
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

String::split_ascii_whitespace返回一个SplitAsciiWhitespace对象,因此我在 的签名中使用了它handle_tokens,但std::str::SplitAsciiWhitespace它是一个非常特定的类型。字符串列表的通用迭代器更有意义,这样我就可以选择split_whitespace或者只是一个通用的字符串列表。

如何使用文档或编译器错误来概括 的签名handle_tokens


这是我自己尝试回答这个问题的失败尝试:

我可以看到SplitAsciiWhitespace“特征实现”包括:

impl<'a> Iterator for SplitWhitespace<'a>
Run Code Online (Sandbox Code Playgroud)

这就是next()来自的地方(我必须检查源代码来验证这一点)。因此,我尝试使用带有 but 的迭代器fn handle_tokens( mut it: Iterator ) {

error[E0191]: the value of the associated type `Item` (from trait `std::iter::Iterator`) must be specified
  --> src/main.rs:10:27
   |
10 | fn handle_tokens( mut it: Iterator ) {
   |                           ^^^^^^^^ help: specify the associated type: `Iterator<Item = Type>`

Run Code Online (Sandbox Code Playgroud)

好吧,所以Iterator太通用了...我需要告诉编译器它正在包装什么。这是有道理的,否则我将无法取消引用它。我不得不再次查看源代码以了解如何SplitWhitespace实现 Iterator 并看到 type Item = &'a str;所以我尝试指定Itemwith fn handle_tokens( mut it: Iterator<Item = &str>),但是:

error[E0277]: the size for values of type `(dyn std::iter::Iterator<Item = &str> + 'static)` cannot be known at compilation time
  --> src/main.rs:10:19
   |
10 | fn handle_tokens( mut it: Iterator<Item = &str> ) {
   |                   ^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::iter::Iterator<Item = &str> + 'static)`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: all local variables must have a statically known size
   = help: unsized locals are gated as an unstable feature
Run Code Online (Sandbox Code Playgroud)

好的,所以我还需要指定尺寸。str这很奇怪,因为虽然我知道在编译时无法知道的大小,&str但应该知道 的大小。

在这一点上我很困难。我还感到惊讶的是,当 Rust 似乎提供了如此出色的内置文档支持时,源代码检查是必要的。这让我觉得我用来回答这个问题的方法是错误的。

Kit*_*tsu 4

你实际上走在正确的道路上。next确实是在 处定义的Iterator,这就是您需要使用的。你错过的是,它Iterator实际上是一个 *trait`,而不是一种类型。类型可以受特征限制,因此泛型在这里派上用场:

fn handle_tokens<'a, I: Iterator<Item = &'a str>>(mut it: I) { .. }
Run Code Online (Sandbox Code Playgroud)

还有一种特殊的 impl-trait 语法可以用来代替:

fn handle_tokens<'a>(mut it: impl Iterator<Item = &'a str>) { .. }
Run Code Online (Sandbox Code Playgroud)

然而,最后一个例子不能用明确指定的类型来调用,即handle_tokens::<SplitAsciiWhitespace>(iter)