###1.はじめに
今回はSwitch文の条件分岐にタプルの値を使う、通常とは少し違った使い方を紹介しようと思います。場面によっては有効な使い方だと思うので、ぜひご覧ください。
###2.タプルをcaseで使う
まず、タプルを定数のように考えてcaseラベルに置くようにすれば、次のように書くことができます。
ただし、タプルの型はすべて統一されている必要があり、この例では、変数dayが月と日からなる日付を表すタプルを持っていると考えます。
3つだけ書かれているいずれかの祝日に一致すれば表示されます。
switch day {
case (1,1): print("元旦")
case (2,11): print("建国記念の日")
case (5,3): print("憲法記念日")
default: break
}
ある範囲の日付を表すために、範囲演算子が使えます。例えば次の例を確認してください。
switch day {
case (1,1...5): // 1/1 ~ 1/5
print("正月休み")
case (5,3): print("憲法記念日")
case (4,29), (5,2...6):
print("連休")
default: break
}
値を列挙するだけでなく、タプルの要素を取り出して処理に使うこともできます。
このために、caseラベル内にlet、またはvarを記述して、case節の内部でだけ有効な定数、変数を宣言できます。
switch day {
case (5,3): print("憲法記念日")
case (8, let d): print("8/\(d)は夏休みです")
default: break
}
この例では、8月の日付ならいつでも夏休みになります。変数dを使う必要がなければ、「_」を使い次のように記述することもできます。
case (8, _): print("夏休み")
なお、キーワード付きのタプルをswitch文で使用することもできますが、値とcaseラベルで使っているキーワードが一致しない場合にはエラーになります。
タプルとcaseのラベルの対応付けのように、構造と値の一致を調べる処理一般を、Swiftではパターンマッチングといいます。
###3.switch文でwhere節を使う
switch文で、タプルの要素に対して条件を付けることもできます。ここで、日付から曜日を計算する関数dayOfWeekを利用します。この関数は日曜なら0、月曜なら1、というように曜日を整数値で返します。なお、変数yearが西暦年を持つとします。
caseラベルに条件を付ける場合、ラベルと「:」の間に、予約語whereと条件を記述します。以下の例を確認してください。
switch day {
case (1, let d) where d >= 8 && d <= 14 && dayOfWeek(year,1,d) == 1:
print("成人の日")
case (8, _): print("夏休み")
case (let m, let d) where dayOfWeek(year,m,d) == 0:
print("\(m)/\(d)は日曜日")
default: break
}
ここでは、1月の第2月曜日が成人の日であることを条件にしています。
同様に、1年のいつでも日曜日であれば表示するようにしています。
このcaseラベルのように、タプルのすべての要素を定数に割り当てる場合、要素ごとにletを指定することもできますが、タプルの前に1つだけletを記述することもできます。
case let (m, d) where dayOfWeek(year,m,d) == 0:
print("\(m)/\(d)は日曜日")
なお、caseラベルでletやvar、whereを使って条件を指定する方法は、タプルだけでなく、通常の整数などに対しても利用できます。
定数や変数を使うラベルは、別並べると「,」で区切って並べる際に制約があります。
これは、どのラベルの条件に一致したかによって、定数や変数が値を持たない可能性があるからです。
例えば以下のようにすることはできません。
switch t {
case (1, let y), (2, 2):
print("\(y)")
case (2, _):
fallthrough
case (let z, 2):
print("\(z)")
default: break
}
caseラベルで定数や変数を使っているcase節へは、すぐ上の選択肢からfallthrough文で遷移することはできません。
ラベルを「,」で区切って並べた時、それらが定数や変数を含んでよい条件は、すべてのラベルが同じ名前、同じ型の定数もしくは変数を含むことです。
つまり、どんな場合でも定数もしくは変数の値が定まる必要があります。その点だけ気を付けてください。
###4.オプショナル型をswitch文で使う
switch文で場合分けしたい式がオプショナル型の値を含む場合も、caseのラベルで書き分けることができます。
例として名前と年齢からなるタプル型を考えます。ただし、年齢は不明の場合があるのでオプショナル型になっています。
typealias People = (String, Int?)
このような型をSwitch文で扱うには、caseパターンで「?」という記号を使います。
switch m {
case let (name, age?) where age >= 18:
print("\(name), 免許取得可")
case let (name, (15...18)?):
print("\(name), 高校生")
case (let name, nil):
print("\(name), 年齢不明")
default: break
}
このように、対応する定数もしくは変数に「?」を付けると、オプショナル型がnil以外の値を持つときにマッチし、その後のwhere節や実行分では開示演算子を使うことなく値を参照できます。
また、nilを記述しておけば、オプショナル型がnilの値を持つ場合にマッチします。範囲を示すパターンは()で囲みます。
オプショナルであることを示す「?」は、タプルなどの他のパターンに利用することができます。
例えばPepole?型の変数opsをswitch文で使うとすれば、caseには次のように記述できます。
switch ops { // opsはPeople?型
case let (name, 18?)? : // 開示した結果が(文字列, 18)ならマッチする
###5.おわりに
今回はタプルを用いたswitch文の利用法について書きました。次回は列挙型についての記事を書こうと思っているので、よろしければぜひご覧ください。
ここまで見てくださった方、ありがとうございました。