Rust入門(2)「変数と型を学ぼう!」

スポンサーリンク
Rust

今回は、「GitHub CodespacesでRustを始めよう!」の続編である。
まだ、GitHub Codespacesで環境構築をしていない方は、第1回を先にお読みください。

はじめに

前回では、GitHub Codespacesを使ってRustの学習環境を構築し、最初の「Hello, world!」プログラムを実行した。

今回は、プログラミングの基礎となる変数と型について学んでいこう。

今回学ぶこと

  • 変数の宣言と使い方
  • 可変(mutable)と不変(immutable)の違い
  • シャドーイング(shadowing)
  • 基本的なデータ型(整数、浮動小数点数、真偽値、文字)
  • 複合型(タプル、配列)
  • 型変換
  • 定数(const)

準備:体験用プロジェクトを開く

作業場所: trials/02_variables/
このディレクトリで自由にコードを試してみよう。失敗しても問題ない。

Codespacesを開いて、ターミナルで以下のコマンドを実行しよう。

cd /workspaces/rust-practice/trials/02_variables

# VSCodeでファイルを開く
code src/main.rs

# 動作確認
cargo run

これで、体験用プロジェクトの準備が整った。

変数の基本

不変(immutable)変数

Rustの変数は、デフォルトで不変(変更できない)である。これは他の言語と異なる大きな特徴だ。

src/main.rsを開いて、以下のコードを書いてみよう。

fn main() {
    let x = 5;
    println!("xの値は: {}", x);
}
# 実行
cargo run

# 出力
xの値は: 5

変数を変更しようとするとエラー

次に、以下のコードを試してみよう。

fn main() {
    let x = 5;
    println!("xの値は: {}", x);
    
    x = 6; // ← エラーになる!
    println!("xの値は: {}", x);
}

実行すると、エラーが出る.

error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:8:5

エラーの意味

  • 変数xは不変なので、2回代入できない
  • 解決方法:mutキーワードを使う

なぜデフォルトで不変?

Rustは安全性を重視している。変数が不変であれば、予期しない変更によるバグを防げる。変更が必要な場合のみ、明示的にmutを付けることで意図を明確にする。

可変(mutable)変数

変数を変更したい場合は、mutキーワードを使う。

fn main() {
    let mut x = 5;
    println!("xの値は: {}", x);
    
    x = 6;
    println!("xの値は: {}", x);
}
# 実行例
xの値は: 5
xの値は: 6

練習問題 1

以下のプログラムを作成してみよう。

  1. ageという変数を作り、自分の年齢を代入
  2. 年齢を出力
  3. 次の年の年齢を計算して、ageに代入
  4. 新しい年齢を出力

ヒント: mutを使う必要がある。

解答例を見る

fn main() {
    let mut age = 25;
    
    println!("現在の年齢: {}", age);
    
    age = age + 1;
    
    println!("来年の年齢: {}", age);
}

シャドーイング

シャドーイングとは?

同じ変数名で、新しい変数を宣言できる。これをシャドーイングという。

fn main() {
    let x = 5;
    let x = x + 1;
    let x = x * 2;
    
    println!("xの値は: {}", x);
}
//実行例
xの値は: 12

何が起きた?

  • 最初のxは5
  • 2番目のxは6(5 + 1)
  • 3番目のxは12(6 * 2)

シャドーイングとmutの違い

シャドーイングの利点:

型を変更できる

fn main() {
    let spaces = "   ";        // 文字列型
    let spaces = spaces.len(); // 数値型
    
    println!("空白の数: {}", spaces);
}
//実行例
空白の数: 3

mutでは型変更できない。

fn main() {
    let mut spaces = "   ";
    spaces = spaces.len(); // ← エラー!型が違う
}
error[E0308]: mismatched types
  --> src/main.rs:29:14

練習問題 2

以下のプログラムを作成してみよう。

  1. nameという変数に自分の名前(文字列)を代入
  2. 名前を出力
  3. nameをシャドーイングして、名前の文字数(バイト数)を代入
  4. 文字数を出力
解答例を見る

fn main() {
    let name = "太郎";
    println!("名前: {}", name);
    
    let name = name.len();
    println!("名前のバイト数: {}", name);
}

注意: Rustのlen()は文字数ではなくバイト数を返す。日本語は1文字3バイトなので注意しよう。

データ型

Rustには、大きく分けて2種類のデータ型がある。

  1. スカラー型 – 単一の値を表す
  2. 複合型 – 複数の値をグループ化

整数型

整数型の種類

範囲用途
i8-128 〜 127非常に小さい数
i16-32,768 〜 32,767小さい数
i32-2,147,483,648 〜 2,147,483,647デフォルト(通常使う)
i64約-9.2京 〜 9.2京大きい数
i128非常に大きい範囲超大きい数

符号なし整数(0以上の数のみ)

範囲用途
u80 〜 255バイトデータ
u320 〜 4,294,967,295正数
u640 〜 約18.4京大きい正数

デフォルトの型: i32(迷ったらこれを使う)

fn main() {
    let x: i32 = 42;
    let y: u8 = 255;
    let z = 100; // i32と推論される
    
    println!("x = {}, y = {}, z = {}", x, y, z);
}

浮動小数点数型

浮動小数点型

精度用途
f32単精度省メモリ
f64倍精度デフォルト(通常使う)
fn main() {
    let pi: f64 = 3.14159265359;
    let e: f32 = 2.71828;
    
    println!("円周率: {}", pi);
    println!("自然対数の底: {}", e);
}

真偽値型

真偽値型: bool

値: true または false

fn main() {
    let is_adult = true;
    let is_student = false;
    
    println!("成人? {}", is_adult);
    println!("学生? {}", is_student);
}

文字型

文字型: char

特徴:

  • シングルクォート(’)で囲む
  • Unicodeに対応(絵文字も使える!)
  • 4バイト
fn main() {
    let letter: char = 'A';
    let hiragana: char = 'あ';
    let emoji: char = '😀';
    
    println!("文字: {}", letter);
    println!("ひらがな: {}", hiragana);
    println!("絵文字: {}", emoji);
}

練習問題 3

以下の変数を宣言して出力してみよう。

  1. 整数 age(型を明示)
  2. 浮動小数点数 height(身長、単位はcm)
  3. 真偽値 is_programmer
  4. 文字 blood_type(血液型、例: ‘A’)
解答例を見る

fn main() {
    let age: i32 = 25;
    let height: f64 = 170.5;
    let is_programmer: bool = true;
    let blood_type: char = 'O';
    
    println!("年齢: {}", age);
    println!("身長: {} cm", height);
    println!("プログラマー? {}", is_programmer);
    println!("血液型: {} 型", blood_type);
}

複合型

タプル

タプルは、複数の異なる型の値をグループ化できる。

fn main() {
    let person: (String, i32, f64) = (String::from("太郎"), 25, 170.5);
    
    println!("名前: {}", person.0);
    println!("年齢: {}", person.1);
    println!("身長: {}", person.2);
}

分割代入:

fn main() {
    let person = (String::from("太郎"), 25, 170.5);
    let (name, age, height) = person;
    
    println!("名前: {}", name);
    println!("年齢: {}", age);
    println!("身長: {}", height);
}

配列

配列は、同じ型の値を固定長で格納する。

宣言方法:

fn main() {
    // 方法1: 値を列挙
    let numbers = [1, 2, 3, 4, 5];
    
    // 方法2: 型とサイズを明示
    let numbers: [i32; 5] = [1, 2, 3, 4, 5];
    
    // 方法3: 同じ値で初期化
    let zeros = [0; 5]; // [0, 0, 0, 0, 0]
    
    println!("最初の数: {}", numbers[0]);
    println!("2番目の数: {}", numbers[1]);
}

配列の長さ:

fn main() {
    let numbers = [1, 2, 3, 4, 5];
    println!("配列の長さ: {}", numbers.len());
}

練習問題 4

以下のプログラムを作成してみよう。

  1. 自分の情報(名前、年齢、身長)をタプルで作成
  2. 分割代入で各値を取り出す
  3. それぞれを出力
解答例を見る

fn main() {
    let my_info = (String::from("太郎"), 25, 170.5);
    let (name, age, height) = my_info;
    
    println!("名前: {}", name);
    println!("年齢: {} 歳", age);
    println!("身長: {} cm", height);
}



型変換

asキーワード

数値型同士の変換:

fn main() {
    let x: i32 = 100;
    let y: f64 = x as f64;
    
    println!("整数: {}", x);
    println!("浮動小数点: {}", y);
}

注意: 大きい型から小さい型への変換は、データが失われる可能性がある。


文字列への変換

to_string() メソッド:

fn main() {
    let number = 42;
    let text = number.to_string();
    
    println!("数値: {}", number);
    println!("文字列: {}", text);
}

文字列から数値への変換

parse() メソッド:

fn main() {
    let text = "42";
    let number: i32 = text.parse().unwrap();
    
    println!("文字列: {}", text);
    println!("数値: {}", number);
}

注意: unwrap()はエラー時にパニックする。実際のコードでは適切なエラー処理が必要である。


定数

定数とは?

定数(constant)は、プログラム全体で変更されない値である。

変数との違い:

項目変数(let)定数(const)
変更mutで可能不可能
型注釈省略可能必須
命名規則snake_caseUPPER_SNAKE_CASE
const MAX_POINTS: u32 = 100_000;

fn main() {
    println!("最大ポイント: {}", MAX_POINTS);
}

ポイント

  • const キーワードを使う
  • 型を明示する必要がある
  • 大文字のスネークケース(UPPER_SNAKE_CASE)

数値リテラルにアンダースコア(_)を使える(読みやすさのため)

定数の使用例

const PI: f64 = 3.141592653589793;
const MAX_USERS: u32 = 1000;
const APP_NAME: &str = "My Rust App";

fn main() {
    println!("円周率: {}", PI);
    println!("最大ユーザー数: {}", MAX_USERS);
    println!("アプリ名: {}", APP_NAME);
    
    // 計算に使用
    let radius = 5.0;
    let area = PI * radius * radius;
    println!("半径{}の円の面積: {}", radius, area);
}

ここまでの内容を理解できたら、練習問題に挑戦しよう!

練習問題の場所

cd /workspaces/rust-practice/exercises/02_variables
# 練習問題一覧を表示
cargo run --bin variables_exercises

# 個別の練習問題を実行
cargo run --bin ex01_basic
cargo run --bin ex02_shadowing
cargo run --bin challenge01_bmi

学習の進め方

1. 体験する(trials/)

  • ブログ記事を読みながら trials/02_variables/ で試す
  • 自由にコードを書いて実験
  • エラーを恐れず、どんどん試す

2. 練習する(exercises/)

  • 体験が終わったら、docs/02_variables.md(プレビュー表示)を参考にして、 exercises/02_variables/ で練習する
  • 構造化された問題を順番に解く
  • 解答例も用意されている

GitHubに保存しよう

学習内容をGitHubに保存しよう。

cd /workspaces/rust-practice
git add .
git commit -m "Complete variables and types practice"
git push

(参考)私のGitHub: https://github.com/Rocky-Seven/rust-practice

コメント

タイトルとURLをコピーしました