gpt4 book ai didi

rust - Rust 中的迭代器类型

转载 作者:行者123 更新时间:2023-12-03 11:25:43 26 4
gpt4 key购买 nike

我正在学习 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),
}
}
}
String::split_ascii_whitespace 返回一个 SplitAsciiWhitespace 对象,所以我在 handle_tokens 的签名中使用了它,但 std::str::SplitAsciiWhitespace 是一种非常特殊的类型。字符串列表的通用迭代器更有意义,因此我可以选择 split_whitespace 或者只是一个通用的字符串列表。
如何使用文档或编译器错误来概括 handle_tokens 的签名?

这是我自己尝试回答问题的失败尝试:
我可以看到 SplitAsciiWhitespace "Trait Implementations"包括:
impl<'a> Iterator for SplitWhitespace<'a>
这就是 next() 的来源(我必须检查源代码来验证)。因此,我尝试使用带有 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>`

好的,所以 Iterator 太通用了,无法使用......我需要告诉编译器它正在包装什么。这是有道理的,否则我将无法取消引用它。我不得不再次查看 source code 以查看 SplitWhitespace 如何实现迭代器并看到 type Item = &'a str; 所以我尝试使用 Item 指定 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
好的,所以我还需要指定一个大小。这很奇怪,因为虽然我知道在编译时无法知道 str 的大小,但 &str 的大小应该是。
在这一点上,我很困。我也很惊讶,当 Rust 似乎提供了如此强大的内置文档支持时,源代码检查是必要的。这让我觉得我用来回答这个问题的方法是错误的。

最佳答案

你在正确的道路上。 next 确实在 Iterator 中定义,这是您需要使用的。你错过的是 Iterator 实际上是一个 *trait`,而不是一个类型。类型可以被一个 trait 所限制,所以这里泛型派上用场:

fn handle_tokens<'a, I: Iterator<Item = &'a str>>(mut it: I) { .. }
还有一个特殊的 impl-trait 语法可以用来代替:
fn handle_tokens<'a>(mut it: impl Iterator<Item = &'a str>) { .. }
但是,最后一个示例不能使用明确指定的类型调用,即 handle_tokens::<SplitAsciiWhitespace>(iter)

关于rust - Rust 中的迭代器类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62931435/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com