case式Gleamでは、case式を使って条件に応じてコードを実行できます。case式を使うと、ある値を1つ以上の_パターン_と照合できます。そうしたパターンの1つが_リテラルパターン_で、これは値をリテラル値(例えば1や"hello")と照合します。
case式はcaseキーワードを使って書きます。
pub fn describe(number: Int) -> String {
case number {
0 -> "Zero"
1 -> "One"
}
}
他の言語のswitch文と似ているように見えるかもしれませんが、パターンマッチングの真価は、他のパターンも組み合わせたときに発揮されます。そのようなパターンの1つが_変数パターン_で、値に変数を割り当てることができます。次の例では、numberが0でなければ、変数iにその値が割り当てられます。
pub fn describe(number: Int) -> String {
case number {
0 -> "Zero"
i -> "Non zero"
}
}
パターンに条件を追加したい場合もあります。これは_ガード_(節)と呼ばれ、ifキーワードを使って追加できます。
pub fn describe(number: Int) -> String {
case number {
0 -> "Zero"
i if i < 0 -> "Negative number"
}
}
パフォーマンス上の理由から、ガードに使えるのは基本的な数学演算子と真偽値演算子だけです。他の関数をガードの中で使うことはできません。
上の例では、すべての入力に一致するパターンがあるわけではありません。コンパイラーがこれを検出し、エラーを出力します。これは_網羅性チェック_と呼ばれます。警告を解消するには、すべてのケースを処理する必要があります。そのために使えるのが_破棄パターン_で、どんな値にも一致するパターンです。
pub fn describe(number: Int) -> String {
case number {
0 -> "Zero"
i if i < 0 -> "Negative number"
_ -> "Positive number"
}
}
// No compiler error
1つの節で複数のパターンを照合できます。各パターンは|で区切ります。ガードは1つの節に1つだけ追加できます。
pub fn describe(number: Int) -> String {
let yell = True
case number {
0 -> "Zero"
3 | 5 -> "One of the first odd prime numbers"
2 | 4 | 6 | 8 if !yell -> "One of the even numbers less than 10"
i if i % 2 == 0 && yell -> "[Yelling] I'm telling you! It's a even nunber"
i if i < 0 -> "Negative number"
_ -> "Positive number"
}
}
// No compiler error
case式は、上から順にそれぞれのパターンと値を照合し、一致するパターンを見つけると、そのパターンに対応する処理を実行します。パターンの順番が重要です!
この演習では、友達と数の当てっこゲームをします。ルールは簡単です。1から100までの数を心の中で選び、友達がその数を当てようとします。友達の助けになるように、選んだ数(42)にどれだけ近いかによって、返事を変えます。それぞれの返事のルールは、次のとおりです。
42のとき:"Correct"41か43のとき:"So close"41より小さいとき:"Too low"43より大きいとき:"Too high"推測への返事を書く4つのタスクがあります。
正解の推測に返事をするreply関数を実装します:
reply(42)
// -> "Correct"
惜しい推測にも返事をするようにreply関数を変更します:
reply(41)
// -> "So close"
低すぎる推測にも返事をするようにreply関数を変更します:
reply(25)
// -> "Too low"
高すぎる推測にも返事をするようにreply関数を変更します:
reply(88)
// -> "Too high"