我目前正在尝试在Rust中编写一个小函数,该函数将通过简单的LISP风格的计算器语言的 token 返回迭代器。我没想到会遇到编译错误。
我第一次编写该函数的尝试是:
fn tokenizer_for<'a, I>(s: &'a str) -> Peekable<I> where I: Iterator<Item=&'a str> {
s.split_whitespace()
.flat_map(
|word| {
word.replace("(", "( ").replace(")", " )").split_whitespace()
}
)
.peekable()
}
但是rustc回答:error[E0308]: mismatched types
--> src/lib.rs:4:5
|
3 | fn tokenizer_for<'a, I>(s: &'a str) -> Peekable<I> where I: Iterator<Item=&'a str> {
| - ----------- expected `std::iter::Peekable<I>` because of return type
| |
| this type parameter
4 | / s.split_whitespace()
5 | | .flat_map(
6 | | |word| {
7 | | word.replace("(", "( ").replace(")", " )").split_whitespace()
8 | | }
9 | | )
10 | | .peekable()
| |___________________^ expected type parameter `I`, found struct `std::iter::FlatMap`
|
= note: expected struct `std::iter::Peekable<I>`
found struct `std::iter::Peekable<std::iter::FlatMap<std::str::SplitWhitespace<'_>, std::str::SplitWhitespace<'_>, [closure@src/lib.rs:6:13: 8:14]>>`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
我发现在返回类型中使用impl
是可行的(我更喜欢):fn tokenizer_for(s: &str) -> Peekable<impl Iterator<Item=&str>> {
s.split_whitespace()
.flat_map(
|word| {
word.replace("(", "( ").replace(")", " )").split_whitespace()
}
)
.peekable()
}
但是我曾希望能够在这两个选项之间进行选择,即使后者似乎可行,甚至可能不会产生泛型函数。在前一种情况下,为什么不能使用
where
子句指定泛型?我已经使用
where
子句来约束以前出现在返回类型中的通用参数。仅当通用参数也出现在函数的参数中时,这才起作用吗?任何更多解释这种区别的细节的引用文献都将特别有帮助。
最佳答案
在Rust中,当您在Item<...>
列表中指定了生存期或类型参数时,将在使用站点上选择这些生存期或类型参数。
该函数签名表明函数的调用者可以选择I
是什么类型:
fn tokenizer_for<'a, I>(s: &'a str) -> Peekable<I> where I: Iterator<Item=&'a str>;
但这不能编译,因为返回类型实际上是对Iter::peekable()
的调用的返回类型(即,来自错误消息std::iter::Peekable<std::iter::FlatMap<std::str::SplitWhitespace<'_>, std::str::SplitWhitespace<'_>, [closure@src/lib.rs:6:13: 8:14]>>
的类型)。另一方面,此签名表示返回类型仅仅是实现
Iterator<Item=&str>>
的一种:fn tokenizer_for(s: &str) -> Peekable<impl Iterator<Item=&str>>;
调用者无法选择那是什么类型。编译器从函数体中推断出实际的类型。
关于types - 从函数返回泛型而在rust中没有泛型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62747289/