パターン
値をマッチさせて分解します。
パターンは単一の値または複合値の構造を表します。例えば、タプル (1, 2)
の構造は2つの要素のカンマ区切りリストです。パターンは特定の値ではなく値の構造を表すため、さまざまな値とマッチさせることができます。例えば、パターン (x, y)
はタプル (1, 2)
と他の任意の2要素のタプルにマッチします。パターンを値とマッチさせるだけでなく、複合値の一部または全部を抽出し、それぞれの部分を定数または変数名にバインドすることもできます。
Swiftには、任意の種類の値に成功裏にマッチするパターンと、実行時に指定された値にマッチしない可能性のあるパターンの2つの基本的な種類のパターンがあります。
最初の種類のパターンは、単純な変数、定数、およびオプションのバインディングで値を分解するために使用されます。これにはワイルドカードパターン、識別子パターン、およびそれらを含む任意の値バインディングまたはタプルパターンが含まれます。これらのパターンに型注釈を指定して、特定の型の値にのみマッチさせることができます。
2番目の種類のパターンは、マッチさせようとしている値が実行時に存在しない可能性がある場合に使用されます。これには列挙ケースパターン、オプションパターン、式パターン、および型キャストパターンが含まれます。これらのパターンは、switch
文のcase
ラベル、do
文のcatch
句、またはif
、while
、guard
、for-in
文のcase
条件で使用します。
パターンの文法
pattern → wildcard-pattern type-annotation?
pattern → identifier-pattern type-annotation?
pattern → value-binding-pattern
pattern → tuple-pattern type-annotation?
pattern → enum-case-pattern
pattern → optional-pattern
pattern → type-casting-pattern
pattern → expression-pattern
ワイルドカードパターン
ワイルドカードパターンは任意の値にマッチし、その値を無視します。アンダースコア (_
) で構成されます。マッチする値を気にしない場合にワイルドカードパターンを使用します。例えば、次のコードは閉区間 1...3
を反復処理し、ループの各反復で現在の範囲の値を無視します。
for _ in 1...3 {
// 何かを3回行います。
}
ワイルドカードパターンの文法
wildcard-pattern → _
識別子パターン
識別子パターンは任意の値にマッチし、マッチした値を変数または定数名にバインドします。例えば、次の定数宣言では、someValue
は Int
型の値 42
にマッチする識別子パターンです。
let someValue = 42
マッチが成功すると、値 42
は定数名 someValue
にバインド(割り当て)されます。
変数または定数宣言の左側のパターンが識別子パターンである場合、識別子パターンは暗黙的に値バインディングパターンのサブパターンとなります。
識別子パターンの文法
identifier-pattern → identifier
値バインディングパターン
値バインディングパターンは、マッチした値を変数または定数名にバインドします。マッチした値を定数名にバインドする値バインディングパターンは let
キーワードで始まり、変数名にバインドするものは var
キーワードで始まります。
値バインディングパターン内の識別子パターンは、マッチした値に新しい名前の変数または定数をバインドします。例えば、タプルの要素を分解し、各要素の値を対応する識別子パターンにバインドできます。
let point = (3, 2)
switch point {
// x と y を point の要素にバインドします。
case let (x, y):
print("ポイントは (\(x), \(y)) にあります。")
}
// "ポイントは (3, 2) にあります。" と出力されます。
上記の例では、let
はタプルパターン (x, y)
の各識別子パターンに分配されます。この動作のため、case let (x, y):
と case (let x, let y):
の switch ケースは同じ値にマッチします。
値バインディングパターンの文法
value-binding-pattern → var pattern | let pattern
タプルパターン
タプルパターンは、カンマ区切りのゼロ個以上のパターンのリストを括弧で囲んだものです。タプルパターンは対応するタプル型の値にマッチします。
型注釈を使用して、特定の種類のタプル型にマッチするようにタプルパターンを制約することができます。例えば、定数宣言 let (x, y): (Int, Int) = (1, 2)
のタプルパターン (x, y): (Int, Int)
は、両方の要素が Int
型であるタプル型にのみマッチします。
タプルパターンが for-in
文や変数または定数宣言のパターンとして使用される場合、それはワイルドカードパターン、識別子パターン、オプションパターン、またはそれらを含む他のタプルパターンのみを含むことができます。例えば、次のコードは無効です。なぜなら、タプルパターン (x, 0)
の要素 0
が式パターンだからです。
let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]
// このコードは無効です。
for (x, 0) in points {
/* ... */
}
単一の要素を含むタプルパターンの括弧は効果がありません。パターンはその単一要素の型の値にマッチします。例えば、次のコードは同等です。
let a = 2 // a: Int = 2
let (a) = 2 // a: Int = 2
let (a): Int = 2 // a: Int = 2
タプルパターンの文法
tuple-pattern → ( tuple-pattern-element-list? )
tuple-pattern-element-list → tuple-pattern-element | tuple-pattern-element , tuple-pattern-element-list
tuple-pattern-element → pattern | identifier : pattern
列挙ケースパターン
列挙ケースパターンは、既存の列挙型のケースにマッチします。列挙ケースパターンは、switch
文のケースラベルや、if
、while
、guard
、for-in
文のケース条件に現れます。
マッチしようとしている列挙ケースに関連値がある場合、対応する列挙ケースパターンは、各関連値に対して1つの要素を含むタプルパターンを指定する必要があります。関連値を含む列挙ケースにマッチするためにswitch
文を使用する例については、関連値を参照してください。
列挙ケースパターンは、オプションでラップされたそのケースの値にもマッチします。この簡略化された構文により、オプションパターンを省略できます。Optional
が列挙型として実装されているため、.none
と.some
は列挙型のケースと同じswitch
に現れることができます。
enum SomeEnum { case left, right }
let x: SomeEnum? = .left
switch x {
case .left:
print("左に曲がる")
case .right:
print("右に曲がる")
case nil:
print("まっすぐ進む")
}
// "左に曲がる" と出力されます。
列挙ケースパターンの文法
enum-case-pattern → type-identifier? . enum-case-name tuple-pattern?
オプションパターン
オプションパターンは、Optional<Wrapped>
列挙のsome(Wrapped)
ケースでラップされた値にマッチします。オプションパターンは、識別子パターンの直後に疑問符が続き、列挙ケースパターンと同じ場所に現れます。
オプションパターンはOptional
列挙ケースパターンの構文糖衣構文であるため、次のコードは同等です。
let someOptional: Int? = 42
// 列挙ケースパターンを使用してマッチします。
if case .some(let x) = someOptional {
print(x)
}
// オプションパターンを使用してマッチします。
if case let x? = someOptional {
print(x)
}
オプションパターンは、for-in
文でオプション値の配列を反復処理し、nilでない要素に対してのみループの本体を実行する便利な方法を提供します。
let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
// nilでない値のみをマッチします。
for case let number? in arrayOfOptionalInts {
print("見つかった \(number)")
}
// 見つかった 2
// 見つかった 3
// 見つかった 5
オプションパターンの文法
optional-pattern → identifier-pattern ?
型キャストパターン
型キャストパターンには、is
パターンとas
パターンの2つがあります。is
パターンはswitch
文のケースラベルにのみ現れます。is
パターンとas
パターンは次の形式を持ちます。
is <#type#>
<#pattern#> as <#type#>
is
パターンは、実行時にその値の型がis
パターンの右側に指定された型と同じである場合、またはその型のサブクラスである場合に値にマッチします。is
パターンはis
演算子のように動作し、両方とも型キャストを行いますが、返された型を破棄します。
as
パターンは、実行時にその値の型がas
パターンの右側に指定された型と同じである場合、またはその型のサブクラスである場合に値にマッチします。マッチが成功すると、マッチした値の型はas
パターンの右側に指定された型にキャストされます。
switch
文を使用してis
およびas
パターンで値にマッチする例については、AnyおよびAnyObjectの型キャストを参照してください。
型キャストパターンの文法
type-casting-pattern → is-pattern | as-pattern
is-pattern → is type
as-pattern → pattern as type
式パターン
式パターンは式の値を表します。式パターンはswitch
文のケースラベルにのみ現れます。
式パターンで表される式は、Swift標準ライブラリのパターンマッチング演算子(~=
)を使用して入力式の値と比較されます。マッチが成功するのは、~=
演算子がtrue
を返す場合です。デフォルトでは、~=
演算子は2つの同じ型の値を==
演算子を使用して比較します。また、次の例に示すように、値が範囲内に含まれているかどうかを確認することで、値を範囲の値とマッチさせることもできます。
let point = (1, 2)
switch point {
case (0, 0):
print("(0, 0) は原点にあります。")
case (-2...2, -2...2):
print("(\(point.0), \(point.1)) は原点の近くにあります。")
default:
print("ポイントは (\(point.0), \(point.1)) にあります。")
}
// "(1, 2) は原点の近くにあります。" と出力されます。
~=
演算子をオーバーロードしてカスタムの式マッチング動作を提供することができます。例えば、上記の例を再記述して、ポイント式をポイントの文字列表現と比較することができます。
// 文字列と整数をマッチさせるために ~= 演算子をオーバーロードします。
func ~= (pattern: String, value: Int) -> Bool {
return pattern == "\(value)"
}
switch point {
case ("0", "0"):
print("(0, 0) は原点にあります。")
default:
print("ポイントは (\(point.0), \(point.1)) にあります。")
}
// "ポイントは (1, 2) にあります。" と出力されます。
式パターンの文法
expression-pattern → expression