🙆
Rust で String の Vec を作る
Rust で文字列 &str の Vec を作るのは簡単です。
vec!["apple", "orange", "grape"]
しかし、ソフトウェアの設計や使っているライブラリによっては String が必要になることもあります。
vec!["apple".to_string(), "orange".to_string(), "grape".to_string()]
まあ、これで動くのですが、それぞれの要素が離れすぎていて、読みづらく感じます。これは Iterator と .map() を使えばマシにはなります。
vec!["apple", "orange", "grape"].iter().map(|s| s.to_string()).collect()
もう少し改良すると、最初に Vec を作る必要はありません。配列のスライスも Iterator を実装しています。
["apple", "orange", "grape"].iter().map(|s| s.to_string()).collect()
更に、要素の型 String は自明なので、.to_string() よりもう少し短い .into() が使えます。
["apple", "orange", "grape"].iter().map(|&s| s.into()).collect()
ただ、これは参照を外すための & が必要になる [1] ので、短くはなっても少し目障りかもしれません。
なぜ、Into では Auto dereference がきかないのか
str の to_string() はこのように実装されていますが、[2]
impl ToString for str {
#[inline]
fn to_string(&self) -> String {
String::from(self)
}
}
Into トレイトはすべての型にたいして以下のように実装されています。[3]
impl<T, U> Into<U> for T
where
U: From<T>,
{
fn into(self) -> U {
U::from(self)
}
}
そのため、次のコードでは、
let _: Vec<String> = ["apple", "orange", "grape"].iter().map(|s| s.into()).collect();
-
sは&&str - Into は
Tに実装されているので、&&strにも実装されている - しかし、
Uのトレイト境界From<T>つまりFrom<&&str>はStringに実装されていない
ということでコンパイルエラーになります。
error[E0277]: the trait bound `String: From<&&str>` is not satisfied
--> src/main.rs:2:72
|
2 | let _: Vec<String> = ["apple", "orange", "grape"].iter().map(|s| s.into()).collect();
| ^^^^ the trait `From<&&str>` is not implemented for `String`
|
= help: the following implementations were found:
<String as From<&String>>
<String as From<&mut str>>
<String as From<&str>>
<String as From<Box<str>>>
and 2 others
Discussion