100日後にRustをちょっと知ってる人になる: [Day 9]プログラム一般概念
Day 9 のテーマ
今日は The Rust Programming Languageの第3章を一通り読んでおこうと思います。
この章は、文字通り Rust 固有の言語仕様というよりは、一般的なプログラム開発に最低限求められる以下の概念を Rust を使って説明しています。
それぞれを見ていこうと思います。
変数
可変性
Rust では変数はデフォルトで不変 (Immutable) になっています。
同じ名前の変数に2回値を設定すようとする、以下のコードを実行しようとすると、
fn main() {
let x = "Hello World";
println!("xの値は {} です", x);
x = "Hello Rust";
println!("xの値は {} です", x);
}
次のようなエラーが発生します。
error[E0384]: cannot assign twice to immutable variable `x`
| x = "Hello Rust";
| ^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
Rust では、値が変更しないということをコンパイラが担保してくれるため、意図しないところで値が変わってしまい発生するバグを回避することができるのです。
この変数を可変として定義し、値を変更可能にする場合は、mut
キーワードを使用します。
let mut x = "Hello World";
変数と定数
let
キーワードではなく、const
キーワード を使って 定数を定義できます。この定数は不変変数のように値を変更することができません。
Rustの定数の命名規則は、 全て大文字でアンダースコアで単語区切り です
変数と定数の違いは以下の点です。
- 定数は型推論されない
- 常に型を注釈する必要があります
- 定数は
mut
キーワードを使って可変にすることができません - 定数はグルーバルスコープも含め、あらゆるスコープで定義可能です
シャドーイング
素手に定義した変数と同じ名前の変数を新しく宣言でき、 新しい変数は、前の変数を覆い隠し(シャドーイング)ます。
fn main() {
let x = 1;
let x = x + 2;
{
let x = x * 3;
println!("インナースコープの値: {}", x); // -> (1+2)*3 = 9
}
println!("アウタースコープの値: {}", x); // -> 1+2 = 3
}
変数を mut
で可変にしているのとは異なり、新しく変数を生成して上書きを行っています。
データ型
Rust における値は全て何らかのデータ型になっています。
スカラー型
スカラー型とは単独の値を表す型のことです。
Rust では以下のスカラー型があります
- 整数型
- 浮動小数点型
- 論理値型
- 文字型
整数型
サイズと符号の有無で以下のような整数型があります。
サイズ | 符号付き | 符号なし |
---|---|---|
8 bit | i8 |
u8 |
16 bit | i16 |
u16 |
32 bit | i32 |
u32 |
64 bit | i64 |
u64 |
arch | isize |
usize |
浮動小数点型
以下の2種類の基本型があります。
-
f32
- 32 bit
-
f64
- 64 bit
- デフォルト
let x = 1.0; // f64
let y: f32 = 2.0; // f32
論理値型
論理値型: bool
論理値として扱える値は true
と false
です。
文字型
文字型: char
- 文字列: ダブルクォーテーション ("")
- 文字型: シングルクォーテーション ('')
複合型
複合型とは複数の値を一つの型にまとめることができる型のことです。
Rust には 2種類の複合型があります。
- タプル型
- 配列
タプル型
タプルは"複数の型"の"何らか値"を一つの型にまとめる方法です。
丸括弧の中にカンマ区切りで値リストを書いて生成します。
let tup = (100, 2.3, 4);
配列
配列はタプルとは異なり全要素が同じ型である必要があります。
Java などの他の言語と異なり、配列のサイズは固定長です。一度宣言すると、サイズの変更はできません。
配列の型は要素の型と要素数で定義します。
- 要素の型:
i32
- 要素数:
5
let a: [i32; 5] = [1, 2, 3, 4, 5];
関数
Rust の関数と変数の命名規則は、スネークケースを使うのが慣例です。
Rustにおいて関数定義は、fn
キーワードで始まり、関数名の後に丸かっこの組が続きます。
波かっこが、コンパイラに関数本体の開始と終了の位置を伝えます。
fn 関数名() {
do something;
}
関数の引数
- 引数: 関数シグニチャの一部になる変数のこと
fn main() {
another_function(1);
}
fn another_function(x: i32) {
println!("x の値は {} です", x);
}
Rust の仕様上のポイント: 関数シグニチャにおいて、各仮引数の型を宣言しなければなりません
関数の戻り値
矢印(->)の後に型を書いて戻り値を宣言します。
fn main() {
let x = five();
println!("x の値は {} です", x);
}
fn one() -> i32 {
1
}
Day 9 のまとめ
プログラムを作るときに必ず必要になる要素、変数, データ型, 関数について追いかけてみました。
Rust 固有の仕様というよりは、一般的なプログラム開発の概念ということでした。
Rust を使ってプログラムを書いていく上での最低限必要なところをおさえてみた、というような Day 9 でした。
Discussion