100日後にRustをちょっと知ってる人になる: [Day 82]書籍: Rust プログラミング完全ガイド その6
Day 82 のテーマ
Day 81 までに Rust の書籍の Rustプログラミング完全ガイド の 1 章から 11 章までを読み終わりました。
- 第1章 Rustを始めよう
- 第2章 数値演算などの基本を把握しよう
- 第3章 オブジェクトに名前を付ける
- 第4章 実行の流れを制御する
- 第5章 データシーケンスを使う
- 第6章 基本のデータ型を使う
- 第7章 列挙と照合
- 第8章 混成的なデータ構造を使う
- 第9章 関数を定義する
- 第10章 ジェネリックな関数や型を定義する
- 第11章 メモリを割り当てる
- 第12章 データの実装
- 第13章 クロージャを定義する
- 第14章 変更可能な文字列を使う
- 第15章 範囲とスライス
- 第16章 イテレータを使う
- 第17章 入出力とエラー処理
- 第18章 データのカプセル化[メソッドとモジュール]
- 第19章 トレイトを使う
- 第20章 オブジェクト指向プログラミング
- 第21章 標準ライブラリのコレクション
- 第22章 所有権、移動、コピー
- 第23章 借用とライフタイム
- 第24章 さらにライフタイムについて
今週中にこの書籍を読み終えるためには少しペースを上げねばと思う今日この頃。さて、今日はどこまで読み進められるでしょうか。というわけで、読んでいきたいと思います。
第12章 データの実装
この章での内容:
- さまざまな方のオブジェクトがスタックに占めるバイト数を調べる方法
- 外部モジュールで宣言された関数をアクセスするパスを短縮する方法
- プリミティブ型のオブジェクトにビットがどう保存されるのか
- オブジェクトがメモリのどこに保存されのかを調べる方法
- パディングによって、ある種のオブジェクトが占めるサイズが増える理由
- ベクターはどの様に実装されるのか
オブジェクトサイズ確認についてメモ
size_of
関数でオブジェクトサイズを確認します。&i8
や &i128
のようなリファレンスのサイズは、メモリアドレスのサイズです。
use std::mem::size_of;
println!("i8:{} i16:{} i32:{} i64:{} i128:{} bool:{} char:{} isize:{} usize:{} &i8:{} &i128:{}",
size_of::<i8>(),
size_of::<i16>(),
size_of::<i32>(),
size_of::<i64>(),
size_of::<i128>(),
size_of::<bool>(),
size_of::<char>(),
size_of::<isize>(),
size_of::<usize>(),
size_of::<&i8>(),
size_of::<&i128>(),
);
i8:1 i16:2 i32:4 i64:8 i128:16 bool:1 char:4 isize:8 usize:8 &i8:8 &i128:8
メモリ上のバイト位置についてメモ
通常コードを書いている上でもは特にアドレスを意識することはないのかもしれません。ですが、厳密なルールも存在するので Rust
におけるメモリへの配置位置のルールについてです。
- プリミティブ型のオブジェクトは、どれもそのサイズの整数倍となるアドレスに置かなければならない。
第13章 クロージャを定義する
この章での内容:
- 引数と戻り値が型推論され、波括弧を書く必要がなく、関数定義の時点で生きていた変数をアクセスできる、という無名のインライン関数がなぜ必要なのか
- そのような軽量関数 (クロージャ) を、どのようにすれば宣言して呼び出せるのか
クロージャについてメモ
クロージャの基本的な書き方は次のようになります。
|arg: T| -> T {
expr_1;
...
expr_n
};
クロージャは引数や戻り値の型が自明であれば省略できます。つまり、次のようなクロージャはすべて同じ意味になります。
- 引数と戻り値の型を指定
let case1 = |x: u32| -> u32 { x + 1 };
- 型を省略
let case2 = |x| { x + 1 };
- 波括弧を省略
let case2 = |x| x + 1 ;
第14章 変更可能な文字列を使う
この章での内容:
- 静的な文字列がどのように実装されるのか
- 動的な文字列がどのように実装されるのか
- 動的文字列で、どうすれば文字の追加や削除ができるのか
- 静的文字列を動的文字列に、あるいはその逆に変換する方法
- 複数の文字列を連結する方法
静的文字列についてメモ
次のように &str
型で定義している文字列は変更できない文字列で、静的文字列と呼ばれます。
let a: &str = "This is String.";
ちなみに、次のように書くとエラーが発生します。
let a: str = "This is String.";
[E0277] Error: the size for values of type str
cannot be known at compilation time
コンパイル時には文字列のサイズを知ることが出来ないというエラーが発生します。
&str
型は str
への参照なのですが、参照だけでなく、ポインタと長さのペアになっています。
動的文字列についてメモ
文字列を実行時に作成したり変更したりする場合には、静的文字列の &str
を使用することができません。
そこで、動的文字列の String
型を使用します。
以下のような String
型の定義方法があります。
let a = String::from("Hello String");
let b = "Hello String".to_string();
let c = "Hello String".to_owned();
let d = format!("Hello String");
動的文字列の結合についてメモ
String
型の扱いはベクタに似ています。ベクタが持つ次のようなメソッドも実装されています。
push
pop
remove
insert
len
let a = "Hello".to_string();
let b = " ".to_string();
let c = "String".to_string();
let mut result = String::new();
result.push_str(&a);
result += &b;
result.push_str(&c);
println!("{}",result);
String 型文字列を結合する時に push
で連結していますが、+=
も使用できます。この +=
は push
のシンタックスシュガーです。
Day 82 のまとめ
今日は 12 章のメモリ上のオブジェクトサイズ、 13 章のクロージャの使い方、そして 14 章の静的文字列と動的文字列について読み進めてみました。
-
第12章 データの実装
- さまざまな方のオブジェクトがスタックに占めるバイト数を調べる方法
- 外部モジュールで宣言された関数をアクセスするパスを短縮する方法
- プリミティブ型のオブジェクトにビットがどう保存されるのか
- オブジェクトがメモリのどこに保存されのかを調べる方法
- パディングによって、ある種のオブジェクトが占めるサイズが増える理由
- ベクターはどの様に実装されるのか
-
第13章 クロージャを定義する
- 引数と戻り値が型推論され、波括弧を書く必要がなく、関数定義の時点で生きていた変数をアクセスできる、という無名のインライン関数が なぜ必要なのか
- そのような軽量関数 (クロージャ) を、どのようにすれば宣言して呼び出せるのか
-
第14章 変更可能な文字列を使う
- 静的な文字列がどのように実装されるのか
- 動的な文字列がどのように実装されるのか
- 動的文字列で、どうすれば文字の追加や削除ができるのか
- 静的文字列を動的文字列に、あるいはその逆に変換する方法
- 複数の文字列を連結する方法
あと 2 日で全部読み終えることできるかな。
Discussion