rust: Rustがんばろう 10日目
2025/04/08
はじめに
そうだ、私はそういえば Rust の勉強をしていたのだった。
- 2025/02/22 rust: Rustがんばろう 9日目 - hiro99ma blog
そんな記憶すらもう過去のものだ。
前回何をしていたか
8章のまとめにある課題をやっていたようだ。
8章はコレクション関係で、Vec<T>、String、HashMap<K,V> の紹介が行われている。
String
未だにピンと来てないのは String 関係だ。
そろそろ “The Rust Programming Language” 以外の資料も見た方がよいのかもしれないが、
もうしばらくはこのドキュメントでの見方で学習し、その後で他の視点を参考にしていこう。
strは文字スライス- 通常は借用の
&strという形strは Dynamically Sized Types だから&strのようなポインタ型でしかインスタンスにできないそうだ- Dynamically Sized Types は “DST” と略すようだ
- コンパイル時にサイズが決定しなければ DST
- スライスやトレイトオブジェクトも DST だそうだ
- プリミティブ型 Textual types の 1つ
- 通常は借用の
Stringは標準ライブラリにある文字列型- 標準ライブラリには他の文字列型もあるが、Rust で「文字列」といった場合は
Stringか&strを指すと思っていて良い
use std::collections::HashMap;
fn main() {
let mut scores: HashMap<String, i32> = HashMap::new();
scores.insert(String::from("Blue"), 10);
for v in scores {
println!("{} - {}", v.0, v.1);
}
}
たとえば HashMap<&str, i32> にすると .as_str() を付けたりして型だけあわせてもダメだ。
let mut scores: HashMap<&str, i32> = HashMap::new();
scores.insert(String::from("Blue").as_str(), 10);
“temporary value dropped while borrowed” となるのはこういう流れだろうか。
String::from()でインスタンスが作られる- そのインスタンスのメソッド?
.as_str()が呼ばれるが、HashMap<>の Key になるのは借用した&strだけ scores.insert()が終わるとString::from()のインスタンスは不要なので解放したいが借用されているのでそうはいかない- エラーじゃ
String::from()のインスタンスをあらかじめ作っておけばエラーにならない。
なのでここの原因は型がどうこうではなく所有権がらみということだ。
String::from().as_str() という書き方はどこであってもダメってことだね。
let mut scores: HashMap<&str, i32> = HashMap::new();
let v = String::from("Blue");
scores.insert(v.as_str(), 10);
おなじ v を使い回してもエラーにならない。
まあ、値を上書きするわけじゃないしね。
let v = String::from("Blue");
scores.insert(v.as_str(), 10);
let v = String::from("Yellow");
scores.insert(v.as_str(), 50);
では v を mut にして代入したら?とやってみたが、
mut じゃなくていいよね、ということだと思われる警告が表示される。
代入する箇所はエラーで、借用してるのにそんなことしたらいかんよ、というところか。
let mut v = String::from("Blue");
scores.insert(v.as_str(), 10);
v = String::from("Yellow");
i32 などは mut にすると代入ができるようになるが、struct みたいなやつはメソッドを呼び出して中身に変更を及ぼすという意味になる気がする。
まだねー、そういうのが理屈で説明できないのだ。
ともかく、今回は最初の書き方が一番素直で楽ということになる。
use std::collections::HashMap;
fn main() {
let mut scores: HashMap<String, i32> = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
for (key, value) in scores {
println!("{} - {}", key, value);
}
}
C言語の気持ちだと、どうせヒープに割り当ててるんだろうから & を付けてアドレスだけでいいんじゃないのという気持ちになるのだ。
Rust の & なので違うとは分かっているのだが、インスタンスを直接引数に入れ込むことに抵抗があるのよねぇ。