case(他の言語ではしばしばswitchと呼ばれます)は、if-elseのような制御式の一種です。
caseを使うと、複数のif-else-if文をつなげることができ、より読みやすく、強力な構造も作れます。
caseは、caseキーワードのあとに省略可能な式を続けて定義します。
次に、各ケースでwhenキーワードを使い、そのあとにcase式と比較する式を書きます。
whenキーワードはcaseキーワードと同じインデントにします。
whenキーワードのあとには、case式がwhen式と一致したときに実行するコードを書きます。
caseでは、どのケースにも一致しなかったときに実行される省略可能なelse文を書けます。
case式が評価され、次にそれぞれのwhen式と比較されます。
比較にはcase包含演算子(===)を使います。
case 1
when 1
puts "One"
when 2
puts "Two"
else
puts "Other"
end
# => One
# This is the same as:
tmp = 1
if 1 === tmp
puts "One"
elsif 2 === tmp
puts "Two"
else
puts "Other"
end
===)case包含演算子(===)は、等価演算子(==)とは少し違います。
この演算子は、右辺が左辺の表す集合の要素かどうかを調べます。
つまり、各オペランドをどちら側に置くかが重要です。
どのように動作するかは左辺の型によって変わります。たとえばRangeなら右辺がその範囲に含まれるかどうかを調べ、Objectなら右辺がObjectのインスタンスかどうかを調べます。
(1..3) == 1 # => false
(1..3) === 1 # => true
String == "foo" # => false
String === "foo" # => true
caseでは、複数の式をカンマで区切って指定し、1つのケースで照合できます。
いずれかの式が一致したときにコードを実行します。
1つのケースに複数の候補値がある場合に便利です。
case 1
when 1, 2
puts "One or two"
else
puts "Other"
end
caseでは、値が範囲に含まれるかどうかも調べられます。
これは、when式に範囲を指定して行います。
case var
when 1..3
puts "One to three"
else
puts "Other"
end
case式が必要ないときは、省略できます。 こうすると、各when式が真偽値として評価されます。 その結果、if-else-if文のように動作します。
case
when 1 == 1
puts "One is equal to one"
when 1 > 2
puts "One is greater than two"
else
puts "Other"
end
Crystalでは、1行で書くcase文が使えます。
単純な1行の文を書くときに使えます。
1行で書くときは、when <expression> then <statement>.のように書きます。
また、else文で使うときは、else <statement>のように書きます。
case var
when 1 then puts "One"
when 2 then puts "Two"
else puts "Other"
end
caseでは、型との照合ができます。
比較にはis_a?演算子を使って、変数の型を調べます。
たとえば、ユニオン型の各型ごとに分岐できます。
case var
when Int32
puts "Int32"
when String
puts "String"
else
puts "Other"
end
caseでは、暗黙のオブジェクトを使えます。
これにより、たとえばwhen式をcase式に対するメソッド呼び出しにできます。
メソッドが真値または偽値を返すかどうかに基づいて、そのケースが一致するかどうかが決まります。
case 1
when .odd?
puts "Odd"
when .even?
puts "Even"
end
caseでは、網羅的なケースを書けます。つまり、考えられるすべての値を処理することを保証できます。
これはwhen文に似ていますが、whenの代わりにinキーワードを使います。
網羅的なcaseでは、when文やelse文は使えません。
網羅的なcaseは、Bools、Union型、Enum、Tuplesに対して使えます。
後半の2つは、後の概念で扱います。
網羅的なcaseでは、すべての可能性を処理しないとコンパイルエラーになります。
Union型を網羅的なcaseとして扱うのは、網羅的でないcaseと似ています。
var : (Int32 | String | Bool)
case var
in Int32
puts "Int32"
in String
puts "String"
in Bool
puts "Bool"
end
Boolsは、trueとfalseキーワードを使って網羅的なcaseとして扱えます。
var : Bool
case var
in true
puts "True"
in false
puts "False"
end