← melang

if 文/式

Last Updated: 2026-09-30 12:00

結論

melangでは、ifを手続き処理として使う場合と値を返す式として使う場合で、elseの扱いを分ける。

// 手続き処理: elseは書けない。条件に該当しないケースを先に処理してearly returnする
if !condition {
    return handle()
}

process()

// 式: elseが必須
x = if condition {
    foo()
} else {
    bar()
}

手続き処理でelseを禁止する代わりに、次のように書くことになる。

// NG: 手続きのelse
if condition {
    process()
} else {
    handle()
}

// OK: 該当しないケースを先に処理する
if !condition {
    return handle()
}

process()

つまりelseは、「手続きのもう一方を実行するための構文」ではなく、値の分岐を完成させるための構文として位置付ける。

狙い

このnoteで決めないこと

次の論点は、このnoteでは決めず、別の機会に扱う。

他言語比較

ifとelseの扱いは、「ifが式か文か」と「elseが必須か任意か」で整理できる。Rust・Kotlin・Scala・Zig・OCaml・Haskellなどはifを式として扱い、Java・C#・C・C++・Go・Python・JavaScript・TypeScript・PHPなどはstatementとして扱って、値の分岐には三項演算子などを別に用意する。

言語`if`は式か`else`の必須性手続きの`else`説明
Rust`if`自体が式任意(値を使うなら必須)`else`も書ける
MoonBit`if`自体が式任意(値を使うなら必須)`else`も書ける
Swiftstatement(5.9以降は式としても可)式では必須、statementでは任意`else`も書ける(`guard`もある)
Kotlin`if`自体が式式として使うなら必須、statementでは任意`else`も書ける
Javastatementのみ(三項演算子・switch式で代替)任意(三項演算子は必須)`else`も書ける
Scala`if`自体が式任意(なければ`Unit`)`else`も書ける
C#statementのみ(三項演算子・switch式で代替)任意(三項演算子は必須)`else`も書ける
C++statementのみ(三項演算子で代替)任意(三項演算子は必須)`else`も書ける
Cstatementのみ(三項演算子で代替)任意(三項演算子は必須)`else`も書ける
Gostatementのみ(三項演算子なし)任意`else`も書ける(慣習はearly return)
Zig`if`自体が式式として使うなら必須、statementでは任意`else`も書ける
OCaml`if`自体が式任意(なければthen側が`unit`である必要がある)`else`も書ける
F#`if`自体が式任意(なければthen側が`unit`である必要がある)`else`も書ける
Haskell`if`自体が式常に必須手続きの`if`は`when`などで代替
Erlang`if`自体が式(ガード式のみ)`else`キーワードなし(`true ->`で代替)`true ->`節で書ける
Elixir`if`自体が式(マクロ)任意(なければ`nil`)`else`も書ける
TypeScriptstatementのみ(三項演算子で代替)任意(三項演算子は必須)`else`も書ける
JavaScriptstatementのみ(三項演算子で代替)任意(三項演算子は必須)`else`も書ける
PHPstatementのみ(三項演算子・match式で代替)任意(三項演算子は必須)`else`も書ける
Ruby`if`自体が式任意(なければ`nil`)`else`も書ける
Pythonstatementのみ(条件式で代替)任意(条件式は必須)`else`も書ける

Rust・Kotlin・Swift・Zigとの違い

Rustはifを式として扱い、elseは任意である。elseがない場合は()が返るため、手続き的なifと値を返すifが同じ構文で表現される。

Kotlin・Zigもifを式として扱い、値として使う場合はelseが必要になる。elseがないifはstatementとしてのみ使える。この点はmelangの設計に近い。ただし、どちらも手続き的なif ... elseを許可するため、melangはさらにelseの用途を制限する。

Swiftの通常のifはstatementで、elseは任意である。guardはelseが必須で、return / break / continue / throwなどでスコープから脱出しなければならない。「手続き的なelseをなくして、early returnを促す」というmelangの思想は、guard ... elseに近い。ただしmelangでは新しい構文を追加せず、通常のifのelseを制限することで実現する。

Go・Haskellが示す2つの方向

Goはifがstatementで、三項演算子もない。一方で、returnで終わるbranchのあとにelseを書かないという慣習があり、early returnが文化として定着している。melangは、この慣習を言語仕様として強制する。

Haskellはifが式で、elseが常に必須である。条件付きの副作用はwhenのような関数で表し、手続きのifと値のifが別の仕組みに分かれている。「値のifはelseが必須」という点は同じだが、melangは手続きのifを構文として残す。

トレードオフ

ifが式で、elseが任意の設計(Rust, Scala, Ruby, Elixirなど)

ifはstatementで、値の分岐は別の構文を使う設計(Java, C#, C, C++, Python, JavaScript, TypeScript, PHPなど)

ifが式で、値として使うときだけelseが必須な設計(Kotlin, Swift 5.9以降のif式, Zig, OCaml, F#, Haskellなど)

melangの選択

melangは、手続きのelseを禁止し、式としてのifではelseを必須にする。

書き手にelseの選択肢を与えるよりも、early returnに寄せた読みやすさと、式と手続きの区別を優先する。