こんばんは。 Rust、よく型を明示的に変換しますよね。
&str
からString
とか、Vec<T>
から&[T]
とかが代表ですが、他にも標準ライブラリだけでもいろいろな変換メソッドが用意されています。
ところでこれらの変換メソッド、名前がas_str()
とかto_string()
とかinto_vec()
とかだったりして前置詞が紛らわしいんじゃ! と思ったことはありませんか? 実はこれにはちゃんと法則性があるということに、Rust歴7年の私はたった今気づきました。
as_***
&self
をとって、同じlifetimeの参照を返すメソッドです。 要するに、ただ参照をキャストしているだけか、メンバへの参照を返しているだけです。 標準ライブラリから適当に例を挙げると、
impl String {
fn as_str(&self) -> &str;
}
impl<T> Vec<T> {
fn as_slice(&self) -> &[T];
}
impl<T> Option<T> {
fn as_ref(&self) -> Option<&T>;
}
などです。 Option<T>
のはちょっと特殊ですが、まぁ気持ちはわかるのでいいです。
to_***
&self
をとって、新しくオブジェクトを作って返すメソッドです。 as_***
と違い、多くの場合&self
と戻り値の間にlifetimeの関係がないのが特徴です。 標準ライブラリでは例えば、
impl i32 {
fn to_string(&self) -> String
}
impl<T> [T] {
fn to_vec(&self) -> Vec<T> where T: Clone;
}
impl<'a, T> Cow<'a, T> {
fn to_mut(&mut self) -> &mut <T as ToOwned>::Owned;
}
などがあります。 最後のCow
の例は特殊で、新しくオブジェクトを作るかもしれないし作らないかもしれないメソッドです。 これはas
とto
の境界にいる感じがしますね。
into_***
self
を食べて(&self
ではない点に注意)、何かを返すメソッドです。 self
は食べられるので以後使えなくなるのが特徴です。
impl<T> [T] {
// Box<[T]>の領域を使い回す変換メソッド
fn into_vec(self: Box<[T]>) -> Vec<T>;
}
impl String {
// やはりStringの領域を使い回すメソッド
fn into_bytes(self) -> Vec<u8>;
}
コメント
@lo485764
@mosh(編集済み) 1
Conversions [Rust issue #7087]
ちょうどここで紹介されている規則ですね。
他にも as_ や to_ などの後ろに付く str とか string とか bytes とかは何やねんというルールもちゃんと紹介されている (Naming conventions) ので、 style guidelines は一度読んでおくと幸せになれるかと思います。
和訳してくれている方もいますね
こういう発見性が低い知識を紹介してくれる記事はありがたいです