コンテンツにスキップ

Rustの変数

変数とは、あとで使えるように値に付けておく名前のことです。ラベルを貼った箱をイメージしてください。箱に何かを入れて名前を書いておけば、値をあちこちに何度も書く代わりに、その名前で呼び出せます。

Rustでは、let キーワードで変数を作ります。

fn main() {
let age = 30;
println!("私の年齢は{age}歳です");
}

実行結果:

私の年齢は30歳です
▶ 実際に試してみよう

この行を分解してみましょう。

  • let — Rustに「新しい変数を作ります」と伝えます。
  • age — 自分で決めた変数の名前です。
  • = — 右側の値を、左側の名前に代入(束縛)します。
  • 30 — 保存する値です。

println! の中の {age} は、変数の値を表示します。これを文字列補間(string interpolation)と呼びます。Rustは {age} を、age に入っている値に置き換えてくれます。

Rustの値には、すべて型があります(整数、テキスト、true/false など)。型を宣言しなければならないと思うかもしれませんが、たいていはその必要はありません。Rustが値を見て、型を判断してくれるからです。これを型推論(type inference)と呼びます。

fn main() {
let score = 95; // Rustは整数だと推論する
let name = "Ferris"; // Rustはテキストだと推論する
let is_active = true; // Rustは真偽値だと推論する
println!("{name}: {score}, active = {is_active}");
}

実行結果:

Ferris: 95, active = true
▶ 実際に試してみよう

型をはっきり書きたいときは、コロンのあとに型を書きます。

let score: i32 = 95; // i32 = 32ビットの整数

ほかの言語から来た人が驚くのがここです。Rustでは、一度変数に値を設定すると、デフォルトでは変更できません。「不変」(immutable)とは、変えられないという意味です。

次のコードはコンパイルが通りません。

fn main() {
let count = 1;
count = 2; // ❌ エラー:不変の変数に2回代入することはできない
println!("{count}");
}

コンパイラは、わかりやすいメッセージで止めてくれます。

error[E0384]: cannot assign twice to immutable variable `count`

これは「不変の変数 count に2回代入することはできません」という意味です。なぜ言語がわざわざこんなことをするのでしょうか? 多くのバグは、思いがけないときに値が変わってしまうことから生まれるからです。変更を求めないかぎり変えられないようにすることで、Rustはコードの動きを予測しやすくしてくれます。これは制限ではなく、機能なのです。

mut で変数を変更できるようにする

Section titled “mut で変数を変更できるようにする”

本当に値を変える必要があるときは、mut キーワードを付けます(mutable、つまり「可変」の略です)。

fn main() {
let mut count = 1;
println!("変更前: {count}");
count = 2; // ✅ `mut` があるので、今度は大丈夫
println!("変更後: {count}");
}

実行結果:

変更前: 1
変更後: 2
▶ 実際に試してみよう

シャドーイング:同じ名前を使い回す

Section titled “シャドーイング:同じ名前を使い回す”

Rustでは、前の変数と同じ名前で新しい変数を宣言できます。これをシャドーイング(shadowing)と呼びます。新しい変数が、古い変数に「影を落として」隠してしまうイメージです。

fn main() {
let x = 5;
let x = x + 1; // 古い x をもとにした新しい x -> 6
let x = x * 2; // さらに新しい x -> 12
println!("x は {x} です");
}

実行結果:

x は 12 です
▶ 実際に試してみよう

mut と似ていますが、違うものです。

  • mut は、同じ変数の値を変更します。
  • シャドーイングは、たまたま同じ名前を使っているまったく新しい変数を作ります。しかも、型を変えることもできます。

シャドーイングは、値を変換しつつ同じ名前を使い続けたいときに便利です。

fn main() {
let spaces = " "; // テキスト
let spaces = spaces.len(); // 今度は数値(空白の数)
println!("空白の数: {spaces}");
}

実行結果:

空白の数: 3
▶ 実際に試してみよう

定数とは、決して変わることがなく、コンパイル時に値が決まっているもののことです。let の代わりに const で宣言し、型は必ず書かなければなりません。

const MAX_SCORE: u32 = 100;
fn main() {
println!("最高得点は{MAX_SCORE}点です");
}

実行結果:

最高得点は100点です
▶ 実際に試してみよう

慣習として、定数は UPPER_SNAKE_CASE(大文字とアンダースコア)で書きます。普通の変数との違いは次のとおりです。

let の変数 const の定数
変更できる? mut を付けたときだけ 絶対にできない
型の指定は必要? 任意(推論される) 必須
名前のスタイル snake_case UPPER_SNAKE_CASE
書ける場所 関数の中 どこでも(関数の外でもOK)

1分あたりの秒数や上限値のように、本当に固定された値には定数を使いましょう。

  • snake_case を使います。小文字の単語をアンダースコアでつなぎます(user_name、total_price)。
  • 名前には英字、数字、アンダースコアを使えますが、数字で始めることはできません。
  • 意味のわかる名前を付けましょう。a より age のほうがいい名前です。

1 から始まる変数 level を作ってください。それを表示し、1ずつ2回増やして、変わるたびに表示します。レベル 1、レベル 2、レベル 3 と表示されればOKです。ヒント:変わる値には mut が必要です。level = level + 1; で1増やせます。

解答を見る
fn main() {
let mut level = 1;
println!("レベル {level}");
level = level + 1;
println!("レベル {level}");
level = level + 1;
println!("レベル {level}");
}

実行結果:

レベル 1
レベル 2
レベル 3
▶ 実際に試してみよう

60 を表す定数 SECONDS_PER_MINUTE を宣言してください。let time = 5;(単位は分)から始めて、time をシャドーイングし、同じ長さを秒で表すようにします。そして 300秒です と表示しましょう。ヒント:新しい time は古い time から作れます(let time = time * ...;)。

解答を見る
const SECONDS_PER_MINUTE: u32 = 60;
fn main() {
let time = 5; // 分
let time = time * SECONDS_PER_MINUTE; // 新しい `time`。今度は秒
println!("{time}秒です");
}

実行結果:

300秒です
▶ 実際に試してみよう

mut は必要ありません。2つ目の let は、同じ名前を使ったまったく新しい変数を作るからです。また、ここでRustは time を u32 だと推論します。u32 の定数と掛け算しているからです。

  • 変数は let で作ります。たいていはRustが型を推論してくれます。
  • 変数はデフォルトで不変です。変更できるようにするには mut を付けます。
  • シャドーイングは let で同じ名前を宣言し直して、新しい変数を作ります(型を変えることもできます)。
  • 定数(const)は決して変わらず、型の指定が必須で、UPPER_SNAKE_CASE で書きます。

理解度チェック

1. Rustでは、デフォルトで let の変数に再代入できますか?

2. Rustのシャドーイングとは何ですか?

3. このページによると、Rustの変数にはどの命名規則を使いますか?

スコア: 0 / 3