型に参照を持たせない
構造体のフィールドとかEnumのバリアントに参照を含む (ライフタイム指定を要求する) 型を持たせると、その型自体もライフタイム指定を要求するようになる
汚染ともいえる
code:no_ref.rs
struct WithRef<'a> {
s: &'a str,
}
struct WithoutRef {
s: String,
}
impl にライフタイム引数が要求されたり、その型が登場する関数のシグネチャにライフタイム引数が用意されたりされなかったりする
参照を持たせたほうが効率的だしよさそうに見えるが、ここはYAGNIと叫びながら参照を回避するのが良いと思う 参照と格闘してるうちに開発のモチベが消える→避けられぬ死へ
片手で捻り潰せるようになったらいいのかもしれないけどさあ
型システムが強力な言語ではYAGNIパワーが求められる……
引数がownedなのに返り値が参照を含んでいる場合ほぼ確実に怒られる
1. ownedな引数への参照を返している
code:s.rs
fn part(s: String) -> &str {
&s // ダメです
}
関数が終わった時点でownedな引数の値は解放され、そしてそれへの参照が外に出た場合ダングリングポインタになる) ので、参照を返すことはできない
考えること
本当にその引数はownedな必要があるのか?借用 &s でよくないか?
本当にその返り値は参照な必要があるのか?ownedな値でよくないか?
2. 関数内で生成した値への参照を返している
code:g.rs
fn foo() -> &String {
&String::from("hogehoge")
}
変数も同様に解放されるのでそれを参照したのを返せない
考えること
この参照はownedにできるのでそうする
明日死ぬ宿命の人間が人にものを貸すか?あげちゃってもいいだろ
3. 'static なら怒られない
code:static.rs
const MESSAGE: &'static str = "Rust難しすぎワロタ";
fn get_message() -> &'static str {
MESSAGE
}
staticなら参照先は不死なのでOK
ふつうの型引数として見るとおかしいことがわかりやすいかも
fn p(s: String) -> &str は内部的には fn p<'a>(s: String) -> &'a str になる
fn p<T>(s: String) -> Vec<T> とかあったらキレるだろ
抽象化しない
トレイトを使った抽象化は難易度が一気に上がる