我试图在锈蚀中使用Chain,但遇到了一个对我来说很奇怪的问题。我尝试了两个代码片段,其中一个工作,另一个不能。我试图从编译器发出的错误信息中找出问题,但找不到任何有用的东西。
fn main() {
let v: Vec<_> = (1..5).collect();
let u = v.iter().chain([6, 7, 8, 9, 10].iter().map(|i| i ));
u.for_each(|i| println!("{i}"));
}fn main() {
let v: Vec<_> = (1..5).collect();
let u = v.iter().chain([6, 7, 8, 9, 10].iter().map(|i| i+1 ));
u.for_each(|i| println!("{i}"));
}第一个片段成功运行,但第二个片段失败。错误信息是:
Compiling playground v0.0.1 (/playground)
error[E0271]: type mismatch resolving `<[closure@src/main.rs:5:56: 5:63] as FnOnce<(&{integer},)>>::Output == &{integer}`
--> src/main.rs:5:28
|
5 | let u = v.iter().chain([6, 7, 8, 9, 10].iter().map(|i| i+1 ));
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&{integer}`, found integer
| |
| required by a bound introduced by this call
|
= note: required because of the requirements on the impl of `Iterator` for `Map<std::slice::Iter<'_, {integer}>, [closure@src/main.rs:5:56: 5:63]>`
note: required by a bound in `std::iter::Iterator::chain`
error[E0599]: the method `for_each` exists for struct `std::iter::Chain<std::slice::Iter<'_, {integer}>, Map<std::slice::Iter<'_, {integer}>, [closure@src/main.rs:5:56: 5:63]>>`, but its trait bounds were not satisfied
--> src/main.rs:6:7
|
6 | u.for_each(|i| println!("{i}"));
| ^^^^^^^^ method cannot be called on `std::iter::Chain<std::slice::Iter<'_, {integer}>, Map<std::slice::Iter<'_, {integer}>, [closure@src/main.rs:5:56: 5:63]>>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`<Map<std::slice::Iter<'_, {integer}>, [closure@src/main.rs:5:56: 5:63]> as Iterator>::Item = &{integer}`
which is required by `std::iter::Chain<std::slice::Iter<'_, {integer}>, Map<std::slice::Iter<'_, {integer}>, [closure@src/main.rs:5:56: 5:63]>>: Iterator`
`std::iter::Chain<std::slice::Iter<'_, {integer}>, Map<std::slice::Iter<'_, {integer}>, [closure@src/main.rs:5:56: 5:63]>>: Iterator`
which is required by `&mut std::iter::Chain<std::slice::Iter<'_, {integer}>, Map<std::slice::Iter<'_, {integer}>, [closure@src/main.rs:5:56: 5:63]>>: Iterator`
Some errors have detailed explanations: E0271, E0599.
For more information about an error, try `rustc --explain E0271`.
error: could not compile `playground` due to 2 previous errors我对锈病并不熟悉,也不熟悉很多细节。有人能给我解释一下这里有什么问题吗?为什么将i更改为i+1会导致编译时错误?
发布于 2022-09-17 06:42:07
这在第一种情况下是成功的,因为两个迭代器都在生成&i32项。但是,在第二个例子中,第一个迭代器生成&i32项,而第二个迭代器生成i32项--加法操作i并生成一个整数。要链接两个迭代器,项目类型必须完全匹配。
为了澄清,在这两个片段中给map的闭包签名不同,这可能令人惊讶,因为它们看起来几乎相同!
|i| i接受一个&i32并返回该&i32。在代码片段1中,这等同于|i: &i32| -> &i32 { i }。|i| i + 1接受一个&i32并返回一个i32,它不是相同的类型。在代码片段2中,这等同于|i: &i32| -> i32 { *i + 1 }。要解决这个问题,请使用copied实用程序通过复制将第一个迭代器从&i32项转换为i32项,这将与第二个迭代器的类型相匹配,从而允许链接:
fn main() {
let v: Vec<_> = (1..5).collect();
let u = v.iter().copied().chain([6, 7, 8, 9, 10].iter().map(|i| i+1 ));
u.for_each(|i| println!("{i}"));
}或者,将Vec转换为带有into_iter的interator,这将消耗Vec并直接生成其值(而不是作为引用)。
fn main() {
let v: Vec<_> = (1..5).collect();
let u = v.into_iter().chain([6, 7, 8, 9, 10].iter().map(|i| i+1 ));
u.for_each(|i| println!("{i}"));
}类型推断可以方便,但也可以向您隐藏信息。当您遇到像这样的“类型不匹配”错误而无法解决它们时,诊断问题的一个好方法是根据您认为类型的实际情况开始添加类型注释。添加的类型注释将通过强制错误推断的类型来解决问题,或者Rust会抱怨类型注释与实际类型不匹配,这将暴露您不正确的假设,从那里您应该能够解决问题。
在这种情况下,将返回类型注释-> &i32添加到第二个闭包将导致一个更容易理解的错误:
error[E0308]: mismatched types
--> src/main.rs:6:28
|
6 | .map(|i| -> &i32 { i+1 } )
| ^^^
| |
| expected `&i32`, found integer
| help: consider borrowing here: `&(i+1)`编译器的建议是不正确的,但这使情况更加清楚,并帮助您看到,当您从第一个代码段中想到它将返回i32时,您的闭包正在返回&i32。
https://stackoverflow.com/questions/73752564
复制相似问题