以下代码无法编译
fn main() {
let n = 10;
let mut s = String::new();
let v = vec!['a'; n];
s += &v.into_iter().collect();
}
出现错误:
error[E0277]: a collection of type `str` cannot be built from an iterator over elements of type `char`
--> src/main.rs:5:25
|
5 | s += &v.into_iter().collect();
| ^^^^^^^ a collection of type `str` cannot be built from `std::iter::Iterator<Item=char>`
|
= help: the trait `std::iter::FromIterator<char>` is not implemented for `str`
但是此修改似乎可行:
fn main() {
let n = 10;
let mut s = String::new();
let v = vec!['a'; n];
let t: String = v.into_iter().collect();
s += &t;
}
我正试图了解原因。任何提示/解释都会有所帮助。谢谢。
答案 0 :(得分:4)
首先,有效的方法:
fn main() {
let n = 10;
let mut s = String::new();
let v = vec!['a'; n];
s += &v.into_iter().collect::<String>();
}
其次,让我们探讨一下为什么可行。您可以在+=
上添加String
,因为它实现了AddAssign
trait:
impl<'_> AddAssign<&'_ str> for String
,但仅当右侧是&str
时。因此,在您的第一个示例中,rustc
尝试将char
的向量收集到str
中。由于Iterator::collect
的签名而无法使用:
fn collect<B>(self) -> B
where
B: FromIterator<Self::Item>,
指示只能将迭代器收集到实现FromIterator
的容器中。在所有执行implement it的类型中,您可以看到str
不是其中之一,而String
是其中之一。那就是您所看到的错误消息。
另一方面,在第二个示例和此答案中的代码中,明确要求rustc
收集到String
中。而且由于String
以str
作为目标类型实现了Deref
trait:
impl Deref for String {
type target = str;
}
&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>>();
}