我正在学习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
太泛泛了,我需要告诉编译器它封装的是什么。这样才有意义,否则我就无法解引用它。我不得不再次查看源代码来查看SplitWhitespace
如何实现迭代器,并看到 type Item = &'a str;
所以我尝试使用fn handle_tokens( mut it: Iterator<Item = &str>)
来指定Item
,但是遇到了问题:
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 提供了如此出色的内置文档支持时,我也感到惊讶需要进行源代码检查。这使我认为我回答这个问题的方法是错误的。
where
、IntoIterator
和Borrow
还不是我掌握的内容。@Kitsu 的回答非常清晰。 - Stewart