コンテンツにスキップ

Rustの真偽値

真偽値(boolean)は、いちばんシンプルな型です。取りうる値は true(真)か false(偽)の2つだけです。Rustでは bool と呼ばれ、コードの中で何かを判断する必要がある場面ならどこでも使います。

fn main() {
let is_active = true;
let has_error: bool = false;
println!("有効: {is_active}、エラー: {has_error}");
}
▶ 実際に試してみよう

Rustは true/false を見るだけで、ほぼ必ず bool だと推論してくれます。そのため、型をはっきり書く必要はめったにありません。

真偽値はたいてい比較から生まれる

Section titled “真偽値はたいてい比較から生まれる”

実際のコードでは、true や false を直接書くことはあまりありません。たいていは、何かを比較した結果として得られます。

fn main() {
let age = 20;
let can_vote = age >= 18;
println!("投票できる: {can_vote}");
}

実行結果:

投票できる: true
▶ 実際に試してみよう

bool のいちばん大事な仕事は、if のどの分岐を実行するかを決めることです。

fn main() {
let is_raining = true;
if is_raining {
println!("傘を持っていこう");
} else {
println!("傘は家に置いていこう");
}
}

if については if…else のページでしっかり説明します。ここでは、真偽値がなぜ大切なのかを少し味見するだけです。

真偽値の組み合わせと短絡評価

Section titled “真偽値の組み合わせと短絡評価”

&&(かつ)、||(または)、!(否定)には、演算子のページで出会いましたね。これらについて、もうひとつ知っておきたいことがあります。答えがもう決まったら、そこで計算をやめるのです。これを短絡評価(short-circuit evaluation)と呼びます。

  • a && b で a が false なら、全体は必ず false になるので、Rustは b を見ません。
  • a || b で a が true なら、全体は必ず true になるので、Rustは b を見ません。

これは単に速くするための工夫ではありません。左側で右側を守ることができるのです。

fn main() {
let count = 0;
let total = 50;
// count は 0 なので、Rustは `count != 0` で止まり、割り算をしない
let big_average = count != 0 && total / count > 10;
println!("平均が大きい: {big_average}");
let is_weekend = true;
let has_homework = true;
// is_weekend が true なので、`!has_homework` はチェックされない
let can_relax = is_weekend || !has_homework;
println!("のんびりできる: {can_relax}");
}

実行結果:

平均が大きい: false
のんびりできる: true
▶ 実際に試してみよう

0で割ると、プログラムはクラッシュしてしまいます。でも、count != 0 が先にあって false になるので、割り算はそもそも実行されません。左右を入れ替える(total / count > 10 && count != 0)と、割り算が先に実行されます。この例ではコンパイラが気づいてビルドを拒否してくれますが(this operation will panic at runtime、「この操作は実行時にパニックします」)、プログラムの実行中に初めてわかる値だったら、クラッシュしてしまいます。ですから、「安全チェック」は左側に置きましょう。

ある遊園地の乗り物は、身長が 120 cm以上または、8 歳以上でかつ大人と一緒なら乗れます。身長 115、年齢 9、with_adult = true を保存して、この子が乗れるかどうかを表示してください。ヒント:「年齢かつ大人と一緒」の部分は、かっこでまとめましょう。

解答を見る
fn main() {
let height_cm = 115;
let age = 9;
let with_adult = true;
let tall_enough = height_cm >= 120;
let can_ride = tall_enough || (age >= 8 && with_adult);
println!("身長が足りている: {tall_enough}");
println!("乗れる: {can_ride}");
}

実行結果:

身長が足りている: false
乗れる: true
▶ 実際に試してみよう

4で割り切れるけれど100では割り切れない年、または400で割り切れる年がうるう年です。2024 について真偽値 is_leap を求めて表示し、1900 についても同じことをしてください。ヒント:「4で割り切れる」は year % 4 == 0 です。2つ目の let で year と is_leap をシャドーイングできます。

解答を見る
fn main() {
let year = 2024;
let is_leap = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
println!("{year}年はうるう年: {is_leap}");
let year = 1900;
let is_leap = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
println!("{year}年はうるう年: {is_leap}");
}

実行結果:

2024年はうるう年: true
1900年はうるう年: false
▶ 実際に試してみよう
  • bool が持てる値は、true か false のちょうど2つです。
  • 比較(==、<、>= など)の結果は真偽値になります。
  • if の条件は本物の bool でなければなりません。数値や文字列から自動で変換されることはありません。
  • && と || は短絡評価をします。答えがわかった時点で右側を飛ばすので、安全チェックは左側に置きましょう。

理解度チェック

1. age >= 18 のような比較の結果は、どの型になりますか?

2. ほかの言語のように、Rustでも 0 のような整数を if の条件にそのまま使えますか?

3. count != 0 && total / count > 10 で、count が 0 のときはどうなりますか?

スコア: 0 / 3