この記事では、Rustにおける変数とデータ型の基礎について解説します。
変数の概要
変数とは、処理するための情報を保持するための箱です。
この変数は一度情報を入れたらその後情報を変更することができない不変性と、何度でも情報の変更ができる可変性の特徴を持っています。
この不変生と可変性の選択は、変数を定義するタイミングで設定することが可能です。
不変的な変数(定数)の定義
変数を不変的にしたい場合、つまり定数を定義したい場合は、constを使って変数を定義します。
また、型の設定が必須となります。
const VALUES: u32 = 100_000;
可変的な変数の定義
変更可能な変数を定義する場合は、letを使用します。
let values = 1;
また、値のみを可変にし、型については不変にしたい場合はmutを使用します。
let mut values = 1;
mutについて公式では以下のように紹介しています。
例えば、Rustでは、以下のように半角スペースを文字列として持っている変数を再利用することができます。
let spaces = " "; // 1
let spaces = spaces.len(); // 2
この場合、1の時は文字列型として扱い、2の時は数値型として変数spacesは扱うようになります。
このように型の変更を防ぎたい場合には、mutを使用して意図しない型変更を防ぐことができます。
let mut spaces = " ";
spaces = spaces.len();
データ型の概要
Rustは静的型付き言語です。そのため、すべての変数は宣言時に、なんかしらのデータ型を設定する必要があります。
Rustでサポートしているデータ型
Rustでサポートしているデータ型は以下になります。
- 数値型: i8, i16, i32, i64, u8, u16, u32, u64, f32, f64など
- 論理型: bool
- 文字型: char
- 文字列型: String
- 配列型: [T; n]
- ベクタ型: Vec<T>
- タプル型: (T1, T2, …, Tn)
- 構造体型: struct
- 列挙型: enum
- スライス型: &[T]
- トレイト型: trait
- ポインタ型: *const T, *mut T
数値型
数値型(スカラー型)にはi8, i16, i32, i64, u8, u16, u32, u64, f32, f64といったようにいくつかの種類があります。
整数型
整数型は小数点を持たない値です。
i8, i16, i32, i64, u8, u16, u32, u64が該当します。
頭にiがついている場合、「符号付き」、uがついている場合は、「符号なし」という扱いになります。
let x: i32 = -1;
let y: u32 = 1;
符号付きとは、プラス(+)または、マイナス(ー)といった表現を持つことができ、符号なしの場合、絶対値(+1であれば1,-6であれば6)といった形で情報を保持します。
iやuの後ろの数字は保持できる数値を表しています。
以下は公式の文章を引用します。
各符号付きバリアントは、-(2n – 1)以上2n – 1 – 1以下の数値を保持でき、 ここでnはこのバリアントが使用するビット数です。以上から、
The Rust Programming Language 日本語版i8
型は-(27)から27 – 1まで、 つまり、-128から127までを保持できます。符号なしバリアントは、0以上2n – 1以下を保持できるので、u8
型は、0から28 – 1までの値、つまり、0から255までを保持できることになります。
浮動小数点型
浮動小数点型は小数点の情報を保持できます。
f32, f64が該当します。
let rate: f32 = 3.0;
論理型
論理型とは、trueとfalseつまり正か偽かのフラグ情報を保持します。
この論理型はboolという型で使用できます。
let f: bool = false;
文字型
文字型とは、その名の通り文字の情報を保持するための型です。
charという型名で使用できます。
let a: char ='A';
文字列型
文字列型を保持するための型です。
Stringという型名で使用できます。
let message: String ='this is test';
配列型
複数の情報を一つの変数に保持するための型です。
[T; n]という型で使用できます。(Tには型、nには配列の長さを設定します)
let nums: [i32; 5] = [1, 2, 3, 4, 5]; // i32の5要素が固定されている配列
ベクタ型
ベクタ型は可変の配列です。
設定する要素の数だけ、保存領域を確保し配列を可変にします。
Vec<T>という型で使用可能です。
let nums: Vec<i32> = (0..3).collect(); // 0~3の値を要素として設定
タプル型
複数の型の値を一つの変数で保持することが可能です。
(T1, T2, …, Tn)という型で使用できます。
let nums: (i32, f64, u8) = (100, 1.1, 6);
構造体型
一つの変数の中に、あらかじめ複数のメンバー変数や型を定義しておくことができます。
structという型で使用できます。
struct Person {
name: String,
age: u8,
}
fn main() {
let tanaka = Person { ' tanaka ' , 19 };
let sasaki = Person { ' sasaki ' , 21 };
}
列挙型
一つの型定義に対し、複数の型を持たせることができます。
enumを使用することで実現可能です。
enum NUM {
TestFloat(f32),,
TestInt(i32),
}
let floatNum = NUM::TestFloat(1.0);
let intNum = NUM::TestInt(1);
スライス型
スライス型とは、配列から借用した一部のデータを保持するための変数です。
&[T]という型を使用します。
以下の例ではxsという配列の一番最初の要素sliceparts[0]を出力します。
fn get_slice(sliceparts: &[i32]) {
println!(sliceparts[0]);
}
fn main() {
let xs: [i32; 5] = [1, 2, 3, 4, 5];
get_slice(&xs);
}
トレイト型
トレイト型は自身で独自の型を生成し、定義することが可能です。
traitを使って実装します。
trait Test {
fn get_test_price(&self) -> f64;
}
ポインタ型
ポインタ型は、保存している情報の先つまり、メモリアドレスを情報として含む変数の型です。
メモリアドレスの参照は&を付与することで実現できます。
まとめ
今回は、Rustにおける変数とデータ型の基礎について解説しました。
いかがでしたか。
是非この機会にRustに挑戦してみてください。