我目前正在学习 Rust,我想从拥有字符串的项目向量中收集字符串 (&strs) 的引用。
struct Channel {
cid: usize,
name: String,
}
fn main() {
let channels: Vec<Channel> = vec![Channel {
cid: 1,
name: "Hello".to_string(),
}];
let names: Vec<&str> = channels.iter().map(|x| &x.name).collect();
}
此代码无法编译,出现以下错误:
[E0277]: a value of type `Vec<&str>` cannot be built from an iterator over elements of type `&String`
--> src/main.rs:11:61
|
11 | let names: Vec<&str> = channels.iter().map(|x| &x.name).collect();
| ^^^^^^^ value of type `Vec<&str>` cannot be built from `std::iter::Iterator<Item=&String>`
|
= help: the trait `FromIterator<&String>` is not implemented for `Vec<&str>`
= help: the trait `FromIterator<&str>` is implemented for `Vec<&str>`
= help: for that trait implementation, expected `str`, found `String`
note: the method call chain might not have had the expected associated types
--> src/main.rs:11:44
|
7 | let channels: Vec<Channel> = vec![Channel {
| __________________________________-
8 | | cid: 1,
9 | | name: "Hello".to_string(),
10 | | }];
| |______- this expression has type `Vec<Channel>`
11 | let names: Vec<&str> = channels.iter().map(|x| &x.name).collect();
| ------ ^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `&String` here
| |
| `Iterator::Item` is `&Channel` here
note: required by a bound in `collect`
--> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2050:19
|
2050 | fn collect<B: FromIterator<Self::Item>>(self) -> B
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
我可以通过调用 as_str() 来提取字符串切片来使其工作:
let names: Vec<&str> = channels.iter().map(|x| x.name.as_str()).collect();
但是,我想了解为什么需要这样做。根据我的理解,由于 deref 强制, a&String
可以转换为 a &str
。为什么我必须明确使用as_str()
?此外,就性能而言,获取as_str()
与引用某个项目相同吗?
Deref 强制通常按您的预期工作,但它取决于类型推断的棘手细节。特别是,在这种情况下,编译器得出闭包返回的结论
&String
,当它意识到我们需要&str
它时已经太晚了(在 之后collect()
)并且它不会及时返回来修复它。除了以下之外,还有多种方式提示编译器
as_str()
:是的。它只是显式地执行编译器通常隐式执行的操作,但无论哪种方式都需要完成工作。