以下代码无法编译
fn main() {
let n = 10;
let mut s = String::new();
let v = vec!['a'; n];
s += &v.into_iter().collect();
}
Run Code Online (Sandbox Code Playgroud)
有错误:
fn main() {
let n = 10;
let mut s = String::new();
let v = vec!['a'; n];
s += &v.into_iter().collect();
}
Run Code Online (Sandbox Code Playgroud)
然而,这种修改似乎有效:
fn main() {
let n = 10;
let mut s = String::new();
let v = vec!['a'; n];
let t: String = v.into_iter().collect();
s += &t;
}
Run Code Online (Sandbox Code Playgroud)
我试图了解原因。任何提示/解释都会有所帮助。谢谢。
首先,什么有效:
fn main() {
let n = 10;
let mut s = String::new();
let v = vec!['a'; n];
s += &v.into_iter().collect::<String>();
}
Run Code Online (Sandbox Code Playgroud)
其次,让我们探讨一下为什么会这样。您可以执行 add-assign +=,String因为它实现了AddAssigntrait:
impl<'_> AddAssign<&'_ str> for String
Run Code Online (Sandbox Code Playgroud)
但前提是右侧是&str. 因此,在您的第一个示例中,rustc尝试收集charinto的向量str。它不会工作,因为签名Iterator::collect:
fn collect<B>(self) -> B
where
B: FromIterator<Self::Item>,
Run Code Online (Sandbox Code Playgroud)
规定迭代器只能收集到实现FromIterator. 在实现它的所有类型中,您可以看到str不是其中之一,而是String。这就是您所看到的错误消息。
另一方面,在您的第二个示例和此答案中的代码中,rustc专门告诉您收集到String. 并且因为String实现了Dereftrait withstr作为目标类型:
impl Deref for String {
type target = str;
}
Run Code Online (Sandbox Code Playgroud)
a&String可以被强制为&str。编译器现在很高兴。
所以现在您应该能够理解为什么以下看起来很有趣的代码也有效:
fn main() {
use std::borrow::Cow;
let n = 10;
let mut s = String::new();
let v = vec!['a'; n];
s += &v.into_iter().collect::<Cow<'_, str>>();
}
Run Code Online (Sandbox Code Playgroud)