はじめに
こんにちはfujitasan-createです。
今回は動的型付け言語ではあまり意識されない、Rustのデータ型に関して勉強していきます。
API作るときとかにPythonでもデータ型を意識せざるを得ない場合もあるんですが、普段はそこまで関わってこないので改めて確認していきます。
基本型
数のデータ型はPythonだと基本的にintとfloatを使います。
しかし、Rustでは整数だけでも
- i8,u8
- i16,u16
- i32,u32
- i64,u64
- i128,u128
- isize,usize
があります。
8とか16というのは、ビット数で、8ビットを1バイトとしています。
iは符号があり、uは符号がないです。例えば、i8なら-128~127、u8なら0~255のようになってます。
isize、usizeはマシンのポインタサイズに依存しているとのことですが、よくわかりませんでした。
32ビットOS → isize、usize は 32ビット
64ビットOS → isize、usize は 64ビット
とのことです。
floatは
- f32(メモリや処理速度優先)
- f64(精度優先)
があります。
CやC++だと float / double / long double みたいに複数あるらしいです。
迷わないようにシンプルになっているようです。
他にも
- 論理値:bool
- 文字:char
- 文字列:&str(文字列スライス),String(可変の文字列)
があるようです。
コレクション型
コレクション型にはこれらがあります。
- 配列:[T; N](長さ固定)
- スライス:&[T](配列やベクタの一部への参照)
- ベクタ:Vec(長さ可変の配列)
- タプル:(T1, T2, …)
知らない用語がいくつかありますがとりあえず今はデータ型に集中します。
ユーザー定義型
Rustでは、自分でデータ型の定義ができるらしいです。
「何の意味があるんだ?」と思いましたが、思ったよりも使いどころがありそうです。
struct・enumがあり、
構造体、タプル構造体、ユニット構造体、列挙型、型エイリアスなどがあります。
enum Direction {
North,
South,
East,
West,
}
let d = Direction::North;
こういうのは結構使えそうかと思いました。
なんかデータベースかなんかでこういうの見たことがある気がするので、結構あった方が便利なのかなと思います。今のところはそこまで思いつきません。
意味を明確にして、間違いを防ぐという観点で使うメリットがあります。
特殊・スマートポインタ
- Option(ある/ないを表す)
- Result(成功/失敗を表す)
- Box(ヒープ確保)
- Rc / Arc(参照カウント、シングル/マルチスレッド)
というのもあるらしいですが、知らない概念が多すぎてまだわからないです。
もう少し先に進んでから再度確認したいと思います。
スタックとヒープ
メモリの使用の関係で、スタックに置かなければいけないものとヒープに置かなければいけないものの2つに大別されるらしいです。
どういうことかというと、&strは最初から決まっていて、あとからデータの大きさを変えられないのでスタック、Stringは最初に決まっていても、あとから変えられる場合があるのでヒープに置くみたいな感じです。
ヒープというのはプログラムが動いている最中に、必要な分のメモリを OS から借りることらしく、
スタックの場合、メモリを積み上げ、終わったら勝手に片づけてくれますが、
ヒープでは、OS に「○バイト欲しい!」とお願いして、使い終わったら片付ける必要がある
という感じです。(Rustでは所有権とライフタイムの仕組みで、この片付けを自動で安全にやってくれるらしい)
- String → 文字列の長さが変わる
- Vec → 要素を増やせる
- Box → ヒープに直接置くためのスマートポインタ
- HashMap, BTreeMap などのコレクション
これらはヒープに置かないといけません。
おわりに
今回は、Rustのデータ型について学びましたが、新しい概念が多く、派生して学んでいくとどんどん色々なことが出てきて驚きます。
次は、もっと新概念に関しての造詣を深めていきたいです。