Rust学習記録:変数、定数、シャドーイング…基本を徹底解説!

Rust学習記録:変数、定数、シャドーイング…基本を徹底解説!

Rust学習記録:変数、定数、シャドーイング…基本を徹底解説!

こんにちは!今日は、Rustの学習記録をまとめていきます。

今まで、Rustをさらっと触ってはいたのですが、今回は腰を据えて、
The Rust Programming Language 日本語版
を読みながら、じっくり学習を進めています。

この記事では、Rustの基本中の基本である、

  • cargo コマンドの使い方
  • 変数と可変性
  • 定数
  • シャドーイング

について、学んだことを整理していきます。「どこまで読み進めたか」という進捗記録も兼ねていますので、Rust初心者の方の参考になれば幸いです。

超便利!cargo コマンドを使いこなそう

Rustの学習を始めてから、特に意識せず cargo を使っていましたが、改めて調べてみると、非常に便利なツールであることが分かりました。

cargo は、Rustのビルドシステム兼パッケージマネージャです。Rustで開発を行う上で、ほぼ必須のツールと言えるでしょう。

覚えておきたい基本的な cargo コマンドは以下の通りです。

  • cargo new: 新しいプロジェクトを作成
  • cargo build: プロジェクトをビルド
  • cargo run: プロジェクトのビルドと実行を1ステップで実行
  • cargo check: バイナリを生成せずにプロジェクトをビルドし、エラーがないか確認
  • cargo update: プロジェクトの依存関係を更新

cargo は、ビルドの成果物を target/debug ディレクトリに格納します。
(Windows, Linux, macOS でコマンドが共通なのは、地味に嬉しいポイントですね!)

リリースビルド

cargo build には、--release オプションを付けることで、最適化されたリリースビルドを作成できます。

  • cargo build: 開発用ビルド (target/debug)
  • cargo build --release: リリース用ビルド (target/release)

リリースビルドは、コンパイル時間は長くなりますが、実行速度が向上します。

Rustの変数と可変性:letmut

Rustの変数は、デフォルトで不変 (immutable) です。
これは、一度変数に値を束縛したら、後から変更できない、ということです。

変数を作成するには、let キーワードを使用します。


let x = 5; // x は不変 (immutable)

変数を可変 (mutable) にするには、mut キーワードを追加します。


let mut y = 5; // y は可変 (mutable)
y = 6; // OK

不変な変数に再代入しようとすると、コンパイルエラーになります。


let x = 5;
x = 6; // コンパイルエラー: cannot assign twice to immutable variable `x`

Rustがデフォルトで変数を不変にしているのは、安全性と並行性を高めるためです。
コンパイラが「この変数の値は変わらない」と保証してくれるので、安心してコードを書くことができます。

Rustの定数:const

Rustには、変数とは別に、定数 (constants) があります。

定数は、

  • mut キーワードを使用できない (常に不変)
  • 必ず型注釈が必要
  • グローバルスコープを含む、任意のスコープで定義可能
  • 定数式にしかセットできない (関数の呼び出し結果や、実行時に評価される値は不可)

といった特徴があります。


const MAX_POINTS: u32 = 100_000; // 定数 (型注釈は必須)

定数式とはコンパイル時に計算できる値です。

定数はプログラムの実行期間中、定義されたスコープ内でずっと有効です。

定数を適切に使用すると、コードの可読性が向上し、将来的な変更にも強くなります。

定数定義時に数値リテラル内にアンダースコアを挿入できる機能は数値の可読性を高めるために導入されています。


const MAX_POINTS: u32 = 100_000;
↓
const MAX_POINTS: u32 = 100000;

上記は同じ意味として扱われます。

Rustのシャドーイング:変数を「覆い隠す」

Rustには、シャドーイング (shadowing) という面白い機能があります。

シャドーイングとは、前に定義した変数と同じ名前の変数を、let キーワードを使って再宣言することです。
これにより、新しい変数が古い変数を「覆い隠し」、以降はその名前で新しい変数を参照できるようになります。


fn main() {
    let x = 5;      // x は i32 型
    let x = x + 1;  // x をシャドーイング (i32 型)
    let x = x * 2;  // x をシャドーイング (i32 型)

    println!("The value of x is: {}", x); // 12

    let spaces = "   ";  // spaces は &str 型
    let spaces = spaces.len(); // spaces をシャドーイング (usize 型)

    println!("spacesの長さ: {}", spaces); // 3
}

シャドーイングは、mut とは異なり、

  • 変数の型を変更できる
  • 実質的に新しい変数を作成する

という特徴があります。

シャドーイングとmutの使い分け


// シャドーイングの例
fn main() {
let message = "Hello, world!"; // message は &str 型
println!("最初の message: {}", message);

let message = 12345; // message をシャドーイング、i32 型
println!("シャドーイング後の message: {}", message);
}

let message = "Hello, world!";: message という変数を宣言し、文字列リテラル “Hello, world!” を代入しています。この時点での message の型は &str(文字列スライス)です。
let message = 12345;: これは、以前の message をシャドーイングして、新しい message 変数を宣言し、整数値 12345 を代入しています。以前の message の型 (&str) に関係なく、新しい message は整数型 (i32) になります。


// ミュータブル変数の例
fn main() {
let mut greeting = "Hello"; // greeting は mut な &str 型
println!("最初の greeting: {}", greeting);

greeting = "Hi"; // greeting を同じ &str 型で更新
println!("更新後の greeting: {}", greeting);
}

let mut greeting = "Hello";: greeting というミュータブルな変数を宣言し、文字列リテラル “Hello” を代入しています。この時点での greeting の型は &str です。
greeting = "Hi";: これは、greeting が mut で宣言されており、かつ “Hi” が “Hello” と同じ型 (&str) を持つ場合に有効です。型が一致しているので、greeting の値を “Hi” で更新できます。


// ミュータブル変数と型の不一致の例
fn main() {
let mut count = "five"; // count は mut な &str 型
println!("最初の count: {}", count);

count = 5; // コンパイルエラー!count の型は &str, 5 は i32
println!("更新後の count: {}", count);
}

let mut count = "five";: count というミュータブルな変数を宣言し、文字列リテラル “five” を代入しています。この時点での count の型は &str です。
count = 5;: これは、count が mut で宣言されていても、5(整数型)を代入しようとすると、count の型 (&str) と 5 の型 (i32) が一致しないため、コンパイルエラーになります。

ポイント
シャドーイングでは、let キーワードを使って新しい変数を宣言するため、古い変数の型に関係なく、新しい変数の型を自由に設定できます。
mut キーワードを使う場合は、変数の型は最初に宣言された時点で固定され、後から変更することはできません。mut を使用した場合変数の型のあった値のみ再代入が可能です。

今回の学習を終えて

今回は、The Rust Programming Language 日本語版を読み進めながら、

  • cargo コマンド
  • 変数と可変性 (let, mut)
  • 定数 (const)
  • シャドーイング

について学びました。次はデータ型について学習を進める予定です。

静的型付け言語は、覚えることが多くて大変ですが、コンパイラが型チェックをしてくれるおかげで、実行時エラーを減らせるというメリットがあります。
Rustの厳格な型システムは、安全なコードを書く上で非常に重要だと感じています。

今回も、AI (主にGemini) に助けてもらいながら学習を進めることができました。ありがとうAI!

Comments

No comments yet. Why don’t you start the discussion?

    コメントを残す

    メールアドレスが公開されることはありません。 が付いている欄は必須項目です