Menu

Zero の if/else|条件分岐を解説

Zero での ifelse の使い方。ブーリアン条件、各分岐の本体、真偽値強制がない理由、そして match とどう使い分けるかを解説します。

このページのコードはエディタで実行できます — 編集してすぐに結果を確認できます。

基本

Zero の if は他のすべての C 系言語の if とおおむね同じ見た目ですが、注目すべき制限がひとつあります——条件は bool でなければなりません。

条件 value == 42bool です。2 つの i32 間の ==bool を返すからです。両方のアームはそれぞれ文のブロックを含みます。どちらのアームも省略「できそう」です——else は任意——ですが、両方ある場合は両方とも { ... } ブロックでなければなりません。

bool 要件

if value { ... } のように書いて 0""null を falsy として扱う言語もあります。Zero はそうしません。条件は実際の bool でなければなりません。

let count = 0
if count {              // コンパイルエラー: bool が期待されたが i32 だった
    // ...
}

if count == 0 {         // OK
    check world.out.write("nothing to do\n")
}

理由は言語全体に通じるのと同じ——暗黙より明示が勝る、というもの。2 つ目の形を読むエージェントは、何が検査されているかを正確に知ります。1 つ目の形は真偽値ルールを暗黙にし、言語ごとに異なります——Zero はそれをオプトアウトします。

else と else-if

else 句は条件が false のときに実行されます。

条件を else if で連鎖します。

if value < 0 {
    check world.out.write("negative\n")
} else if value == 0 {
    check world.out.write("zero\n")
} else {
    check world.out.write("positive\n")
}

else if は単に括弧を省いた else { if ... }——意味は同じで、インデントが減るだけです。最後の else は任意です。

条件の出どころ

条件は bool に評価されるものなら何でも構いません。

  • bool バインディング: if ok { ... }
  • 比較: if value == 42 { ... }if x < y { ... }
  • 論理結合: if a && b { ... }if pair.left == 1_u8 && pair.right == 2_u8 { ... }
  • bool を返す関数呼び出し: if isReady(world) { ... }

言語のサンプルから取った実例スニペット。

let pair: BytePair = Pair { left: 1_u8, right: 2_u8 }
if pair.left == 1_u8 && pair.right == 2_u8 {
    check world.out.write("type alias ok\n")
} else {
    check world.out.write("type alias broke\n")
}

&& は期待通りに短絡します——左辺が false なら右辺は評価されません。|| も同様です。

いつ match を使うべきか

if/else if の連鎖は、特に条件が構造を共有しない場合の 2 方向や 3 方向の判断には向いています。しかし直和型——choiceenum ——のバリアントで分岐するときは、match が正しい道具です。

比べてみましょう。

// match——網羅的、コンパイラーが検査
match result {
    .ok  => value   { check world.out.write("ok\n") }
    .err => message { check world.out.write("err\n") }
}

対して、

// 直和型に対する if/else——冗長で、間違えやすい
if result.isOk() {
    let value = result.unwrap()
    check world.out.write("ok\n")
} else {
    check world.out.write("err\n")
}

match 形式はバリアント解析を明示し、後でバリアントが追加されてハンドリングを忘れた場合にコンパイラーが文句を言ってくれます。if 形式は ok ではないものをすべて、知らない新しいバリアントも含めて、else 分岐に静かに流します。

目安: ブーリアンには if、バリアントには match

スタイルメモ

人間にとってもエージェントにとってもコードが読みやすくなる、小さな慣習です。

  • 本体は必ず波括弧で囲む。1 行の本体でも { ... } に入れます。波括弧なしの単一文形式はありません。これは意図的で、インデントを信頼できる状態に保ち、C 系言語によくあるバグ源を取り除きます。
  • 最もよくある分岐を先に書く。読み手(とエージェント)は上から下に読みます。
  • 同じくらい明確なら肯定の条件を選ぶ。if isReady は、すべてが同じなら if !notReady より追いやすいです。

次回: while ループ

条件分岐は 何を するかを決め、ループは 何回 するかを決めます。次のドキュメントでは Zero の while ループ を扱います——言語が初期段階で出荷しているループ構文です。

よくある質問

Zero の if 文はどう動きますか?

if 条件 { ... } を、必要に応じて else { ... } 句と組み合わせて使います。条件は bool でなければなりません——Zero は整数や文字列など他の値を真偽値に強制変換しません。例: if value == 42 { check world.out.write("yes\n") } else { check world.out.write("no\n") }

Zero に三項演算子はありますか?

Zero は意図的に表面を小さく保ち、別の condition ? a : b 三項ではなく if / else ブロックを使います。公式サンプルは短いケースでも明示的な分岐を好みます。「式としての if」をサポートしている言語に慣れているなら、Zero は 2 つ目の構文を導入するのではなく、その方向に寄ることを期待してよいでしょう。

Zero で if/else if は連鎖できますか?

はい。分岐の間に else if を書いて条件を連鎖します。if a { ... } else if b { ... } else { ... }choiceenum のバリアントに対するより複雑な分岐は、match を使うほうが網羅的で、コンパイラーがすべてのバリアントを扱ったかを検査します。

なぜ Zero は値を bool に強制変換しないのですか?

Zero の設計哲学は「すべては明示的に」です。暗黙の真偽値解釈——0""null を false と扱う——はバグの定番原因で、エージェントが正確に推論するのが難しい部分です。実際の bool を要求することで、分岐の判断がソースに見え、機械的に検証しやすくなります。

if/else ではなく match を使うべきはいつですか?

choiceenum のバリアントで分岐するときに match を使います。コンパイラーがすべてのケースをカバーしたかを検証してくれます——if/else if の連鎖ではできないことです。等号チェック、比較、短い 2 方向分岐のようなシンプルなブール述語には if/else を使い続けましょう。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める