🙆
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