🍥

Rustの借用を影分身の術(NARUTO)で説明してみた

に公開

こんにちは、うずまきナルトだってばよ!!
どもども、southan(サウサン)です!
今回はタイトル通り、Rustの所有権をNarutoの『影分身の術』で(かなり無理やり)説明してみます。
自分の中ではしっくりきたのですが、皆さんには『余計に分からんってばよ!』と思わせてしまうかもしれません…。
もし分かりにくい部分があっても、どうかお手柔らかにお願いします!」

対象読者

  • Rustの学習を始めたばかりの方
  • Narutoをご存知の方(影分身の術が使えると尚良し)

になります。

そもそも「影分身の術」と「借用」とは?

影分身の術とは?

主人公うずまきナルトの得意忍術
術者のチャクラを等分して、実体を持つ分身体を生成します。


借用 (Borrowing)とは?

Rustのメモリ管理は「値のオーナーは常に1つ」という所有権ルールが軸にあります。
しかし、値を使うたびに所有権を移動させていると、元の変数が使えなくなったり、安易なclone()(複製)の多用でコードが煩雑になったりします。
そこで登場するのが借用です。。所有権を移さずに、参照(&T / &mut T)の形で値を「借りる」ことで、複数の場所から安全にデータへアクセスできます。


「借用」を 「影分身の術」 に当てはめてみる

Rustの概念とNarutoのたとえを一覧にしてみました。

Rust の概念 Narutoたとえ
所有者(本体) ナルト本体(チャクラを持つ)
不変借用 &T 偵察用の影分身:見る・報告するだけ(攻撃不可)。何体でも同時に出せる
可変借用 &mut T 修行用の影分身:“いじる・鍛える・書き換える”ことが許可された特別な分身。同時に一体しか出せない。修行中は、本体も他の分身も同じ修行には関与できない。修行が終わると、経験(変更内容)が本体に還元される。
借用の存続期間 術の持続時間(分身が残っている間の制約)
借用の終了 分身が消える(報告完了・解除)→ 制約が解ける

不変借用 = 偵察用影分身(何体でもOK / ただし見るだけ)

偵察用の影分身は、あくまで情報を集めるのが目的です。

  • 敵の数を見たり、地形を測ったりするだけ。
  • 何体でも同時に偵察に出せる。
  • 本体の状態を変更することはできない(パワーアップできない)

Rustでのコード

let naruto = String::from("うずまきなると");
let bunshin1 = &naruto;      // 偵察分身1
let bunshin2 = &naruto;      // 偵察分身2(同時OK)
println!("偵察分身1が見たナルト: {}", bunshin1);
println!("偵察分身2が見たナルト: {}", bunshin2);
// しかし、偵察分身がいる間は、本体は修行などで変化することはできない
// naruto.push_str("、仙人モード!");// ❌ コンパイルエラー!
// 不変の借用(偵察分身)が存在する間は、所有者(本体)は値を変更できない。

可変借用 = 修行分身(一体だけ / ただし能力を書き換えられる)

修行分身は、新たな術を会得するために本体から送り出されます。

  • 本体が「螺旋丸」しか知らなくても、修行に出た影分身が先に「風遁・螺旋手裏剣」を会得できる。
  • 修行分身を出している間、本体は同じ修行ができず、偵察分身も出せない(修行に集中するため)。
  • 修行が終わり分身が消えると、分身が会得した新しい術は、本体も使えるようになる

Rustでのコード

let mut naruto = String::from("螺旋丸"); // 修行前のナルト

println!("修行前のナルト: {}", naruto);

{
    // 修行分身を出す (可変借用)
    let shugyo_bunshin = &mut naruto;

    // 修行分身が新たな術を会得する (値を書き換える)
    *shugyo_bunshin = String::from("風遁・螺旋手裏剣");
} // 修行分身はここで消える (スコープを抜けて可変借用が終了)

// 修行の成果が本体に反映されている!
println!("修行後のナルト: {}", naruto); // => 風遁・螺旋手裏剣

混在は不可(偵察分身と戦闘分身の同時運用はできない)

Rustの最も重要なルールの一つです。
安全のため、偵察分身(不変借用)と修行分身(可変借用)を同時に出すことはできません。
偵察している最中に、別の誰かが内容を書き換えてしまうと、情報が混乱して危険だからです。

Rustでのコード

let mut naruto = String::from("本体");

let bunshin1 = &naruto; // 偵察分身1 (不変借用) がいる

// let shugyo_bunshin = &mut naruto; // ❌ コンパイルエラー!
                                  // 偵察分身(不変借用)がいる間に、修行分身(可変借用)は出せない。

println!("偵察分身1が見たナルト: {}", bunshin1); // この行で bunshin1 を使っているので、借用はまだ続いている

術の持続時間(借用スコープ)

分身(借用)はいつ消えるのでしょうか?
基本的には、「その分身が最後に使われた直後」に術が解けて消えます。これにより、すぐに本体は別の行動に移れます。

Rustでのコード

let mut naruto = String::from("本体");

// --- 偵察分身 (不変借用) の場合 ---
let bunshin = &naruto;
println!("偵察結果: {}", bunshin);
// ↑ bunshin の最後の使用はここ。この行が終わった時点で偵察分身は消え、借用は終了する。

// --- 修行分身 (可変借用) の場合 ---
// 偵察分身が消えたので、すぐに修行分身を出すことができる
let shugyo_bunshin = &mut naruto;
shugyo_bunshin.push_str(" + 螺旋手裏剣"); // 内容を書き換え
// ↑ shugyo_bunshin の最後の使用はここ。ここで修行分身は消える。

// 全ての分身が消えたので、本体は自由に行動できる
println!("最終形態: {}", naruto); // => 本体 + 螺旋手裏剣

まとめ:影分身の術から学ぶ借用のルール

  • 不変借用の影分身(偵察): &T
    • 何体でも同時に出せる。
    • 対象を読み取ることしかできない
  • 可変借用の影分身(修行): &mut T
    • 同時に一体しか出せない
    • 対象を書き換えることができる。修行の成果は本体に反映される。
    • 修行中は、本体も他の分身も手出しできない。
  • 混在禁止:
    • 偵察分身(不変借用)が一体でもいる間は、修行分身(可変借用)は出せない。
    • 逆もまた然り。

おわりに

いかがでしたでしょうか。
かなり無理やり結びつけたので、かえって分かりづらい部分があったかもしれません。
Narutoの影分身で例えると、本家よりだいぶ性能が制限されてしまいましたね…
この記事が、少しでもRustの「借用」の理解に貢献できたら幸いです!

お読みいただきありがとうございました!!

参考

https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.html

https://amzn.asia/d/3LCYubV

Discussion