nikkie-ftnextの日記

イベントレポートや読書メモを発信

t_wadaさんが『プログラミングRust 第2版』の4章・5章でRustを突然理解したそうなので、私も読んでみる #techramen24conf

はじめに

アイマス19周年おめでとうございます!20周年イヤー楽しみ!
nikkieです。

TechRAMEN関連エントリです。
『プログラミングRust 第2版』の所有権まわり(4章・5章)をざっと読んだログです1

目次

t_wadaさんによるLT「これまでと違う学び方をしたら挫折せずにRustを学べた話」

Rust はこれまで私が学んできた言語とはどう違うのか、どう学んだら突然理解できるようになったのか、自分の体験を話したいと思います。

『プログラミングRust 第2版』を私も読んでいきます!

動作環境

% rustc --version
rustc 1.80.0 (051478957 2024-07-21)
% cargo --version
cargo 1.80.0 (376290515 2024-07-16)

読書メモ:所有権の移動

Rustの所有権ってずっとよく分からない感覚だったので、t_wadaさんのLTで聞いた 4章「所有権と移動」を読みました2

Rustはプログラム中でのポインタの使い方に制約を加えたのだ。(4章冒頭より)

4.1で所有という概念を導入。

  • 値はヒープ上にある
  • 所有者として、関数のスタックフレーム上のローカル変数
    • ヒープ上のバッファ(値がある)を所有
    • ここがポインタですね

Rustではすべての値はその生存期間を決定する唯一の所有者を持つ。(4.1)

そして4.2で値がある所有者から別の所有者へと移動するという考え方が説明されます。
値が別のポインタ(別の所有者のポインタ)から指されるようになるんだ!

Rustでは、ほとんどすべての型が、変数への値の代入、関数への引数の受け渡し、関数からの返り値の返却の際にコピーされず、移動(move)される。(4.2)

所有権の移動って、私は代入の挙動きっかけで知ったのですが、関数呼び出しにも登場してるんですね

体感するサンプルプログラム

4.2.3より

  • 2行目のVec::new()呼び出しで所有権が移動している!
    • 空のベクタ3の値はvが所有するように移動
  • for文では可変なvを、101から105までの整数(i32)からなるベクタとしている
    • このベクタを作る中でも、i.to_string()呼び出し、そして、返り値をベクタのpushに渡す箇所は、どちらも所有権の移動
    • 返した値(String)はベクタのインデックスが所有(図4-9 参照)

ここでベクタの(先頭を1番目として)3番目の要素を取り出そうとします。
ここまでの延長で浮かぶlet third = v[2];と書くと、コンパイルエラー。
これが書けると3番目の要素の移動(3番目の要素が未初期化となる)ため、書けないようにコンパイルエラーです。

移動する代わりに借用もできる

この解消については、5章の「参照」に分かれています。

強調するために、Rustはある値に対する参照を作ることを借用(borrowing)と呼ぶ。(5章冒頭)

移動の代わりに借用すると、コンパイルできます!(サンプルコード参照)
String型への参照(共有参照)ですね。

% cargo run
[]
["101", "102", "103", "104", "105"]
Third element is 103

5章を拾い読み4する中で、なるほどと思ったのが以下。

参照があまりに一般的に使われるので、Rustでは.演算子が、必要に応じて暗黙に左のオペランドを参照解決するようになっているのだ。(5.2.1)

println!マクロもコードとしては.演算子を使うとのこと。
私が認識していない範囲で、借用に助けられていたんですよ!
出力した後も同じ変数で値を扱えるのは、所有権が移動していなかったから、つまり参照の恩恵なんだ!

また、.演算子は、メソッド呼び出しの際に、必要があれば暗黙に左オペランドへの参照を借用する。(5.2.1)

この記載からv.push()は、可変参照を使った(&mut v).push()と同じと理解しました

終わりに

t_wadaさんのLTきっかけに読みたくなった『プログラミングRust 第2版』の4章・5章のログでした。
所有権の移動借用(参照)、この2つの概念の解説で、これまで私は所有権を掴み損なっていたんだなあと思い知りました。

移動は変数への代入だけでなく、関数呼び出しや返り値でも起こっていたんですね。
そしてprintln!マクロでデバッグして、私がRustを分からないなりにも書けていたのは、このマクロのコードが暗黙に借用していたから!(出力したい値の所有権が移動していなかったんだね)
読んだことで、Rustプログラムでやっていることがだいぶ見えるようになりました。

過去に分からないなりに書いたプログラムの理解度もだいぶ上がった感覚です。

Ryeやuvなどもっと読めるようになりたいソースがあるので、引き続きRustに取り組んでいきます。
今回の所有権まわりの理解は、ハーケンな気がします


  1. 帰り道に読むぞ!」、回収しました! #techramen24conf 大満喫のログ。楽しかったです!ありがとうございました! - nikkie-ftnextの日記
  2. といっても、この本は1〜5章まではこの順でとのことだった(まえがき)ので、2章まで読み(ここまででも結構なページ数)、3章はそこそこに4章に飛び込みました
  3. Pythonのリストに相当(2.4)
  4. 結構読んだ疲れもあり、参照の参照など読み返したいところを多々残しています