Contents
識別子パターン(identifier pattern)
識別子パターンはあらゆる値とマッチし、マッチした値を変数名・定数名と結び付けます。例えば、下の定数の宣言ですが、someValueは識別子パターンで、Int型の42とマッチします。
let someValue = 42
マッチが成功すると、42という値は定数名someValueと結び付けられます(代入されます)。
定数宣言、変数宣言の左側が識別子パターンである時、その識別子パターンは暗黙的なバリューバインディングパターンのサブパターンです。
バリューバインディングパターン(value-binding pattern)
バリューバインディングパターンはマッチした値を変数名・定数名と結び付けます。バリューバインディングパターンでマッチした値を定数名と結びつけるにはletキーワードを最初に付けます。マッチした値を変数名と結びつけるにはvarキーワードを最初に付けます。
バリューバインディングパターンの一部である識別子パターンは、マッチした値を新しい変数名・定数名と結び付けます。例えば、タプルの要素を分解して各要素の値を対応する識別子パターンと結びつけることができます。
let point = (3, 2) switch point { // pointの要素をxとyに結びつける。 case let (x, y): print("The point is at (\(x), \(y)).") } // Prints "The point is at (3, 2)."
上のサンプルでは、letが、タプルパターン(x,y)の中のそれぞれの識別子パターンに分配します。この挙動のため、switch文のケースである
case let (x,y):
case (let x, let y):
は同じ値にマッチします。
タプルパターン(tuple pattern)
タプルパターンはカンマで区切られた0個、あるいはそれ以上の要素を丸かっこで囲んだリストです。タプルパターンは対応するタプル型とマッチします。
型注釈を使用することで、マッチするタプル型の種類を制約することができます。例えば、定数宣言
let (x,y):(Int,Int)=(1,2)
の中で、
(x,y):(Int,Int)
のようなタプルパターンを記述すると、そのタプルパターンは、両方の要素がInt型のタプル値にのみマッチします。
工事中🏗
列挙型ケースパターン(enumeration case pattern)
列挙型ケースパターンは既存の列挙型のケースとマッチします。列挙型ケースパターンは
- switch文のcaseラベル
- 条件付きif,while,guard文
- for-in文
で登場します。
工事中🏗
列挙型ケースパターンは、オプショナル型の列挙型ケースにもマッチします。
オプショナルパターン
タイプキャストパターン
タイプキャストパターンは、
- isパターン
- asパターン
の二つがあります。isパターンはswitch文のcaseラベルにのみ登場します。isパターン、asパターンは以下のように記述します。
is type pattern as type
isパターンは、照会対象の値(switchの後ろの値)の実行時の型が、isパターンの右側に指定した型と同じ型であれば、あるいは指定した型のサブクラスと同じ型であれば「マッチした」ことになります。
asパターンは照会対象の値(switchの後ろの値)の実行時の型が、isパターンの右側に指定した型と同じ型であれば、あるいは指定した型のサブクラスと同じ型であれば「マッチした」ことになります。マッチした場合、マッチした値の型が、asパターンの右側で指定された型へとキャストが行われます。
class MediaItem { var name: String init(name: String) { self.name = name } } class Movie: MediaItem { var director: String init(name: String, director: String) { self.director = director super.init(name: name) } } var things = [Any]() things.append(1) things.append(1.00000) things.append(42) things.append(3.14159) things.append("hello") things.append((3.0, 5.0)) things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman")) things.append({ (name: String) -> String in "Hello, \(name)" }) var nnn=0 for thing in things { nnn+=1 print(""" \(nnn)番目の要素の型は\(type(of:thing)); """) switch thing { case 1 as Int: print("11111zero as an Int") case 1 as Double: print("22222zero as a Double") case let someInt as Int: print("33333an integer value of \(someInt)") case let someDouble as Double where someDouble > 0: print("444444a positive double value of \(someDouble)") case is Double: print("55555some other double value that I don't want to print") case let someString as String: print("66666a string value of \"\(someString)\"") case let (x, y) as (Double, Double): print("77777an (x, y) point at \(x), \(y)") case let movie as Movie: print("88888a movie called \(movie.name), dir. \(movie.director)") case let stringConverter as (String) -> String: print(stringConverter("Michael")) default: print("something else") } }
1番目の要素=Int; 11111zero as an Int 2番目の要素=Double; 22222zero as a Double 3番目の要素=Int; 33333an integer value of 42 4番目の要素=Double; 444444a positive double value of 3.14159 5番目の要素=String; 66666a string value of "hello" 6番目の要素=(Double, Double); 77777an (x, y) point at 3.0, 5.0 7番目の要素=Movie; 88888a movie called Ghostbusters, dir. Ivan Reitman 8番目の要素=(String) -> String; Hello, Michael
式パターン(Expression Pattern)
式パターン(expression pattern)は、式の値を表現します。式パターンはswitch文のcaseラベルにのみ登場します。
式パターンで表現されている式(各caseの式)は、インプットされた式(switch
の後ろの式)の値と比較されます。Swift標準ライブラリの~=演算子を用いて比較されます。~=演算子を用いて比較した結果、~=演算子がtrueを返した場合、マッチしたことになります。デフォルトでは、~=演算子は同じ型の二つの値を==演算子を用いて比較します。式パターンで範囲の値を照会(マッチするか調べる)することもできます。その値が範囲に含まれるか、以下のサンプルのような感じです。
let point = (1, 2) switch point { case (0, 0): print("(0, 0) is at the origin.") case (-2...2, -2...2): print("(\(point.0), \(point.1)) is near the origin.") default: print("The point is at (\(point.0), \(point.1)).") } // Prints "(1, 2) is near the origin."
式パターンについて独自のマッチングパターンを定義するため、~=演算子をオーバーロード(上書き定義)することもできます。例えば、pointという式を、座標の文字列表現と比較するように、上のサンプルを書き換えたのが下のサンプルです。
// Overload the ~= operator to match a string with an integer. func ~= (pattern: String, value: Int) -> Bool { return pattern == "\(value)" } switch point { case ("0", "0"): print("(0, 0) is at the origin.") default: print("The point is at (\(point.0), \(point.1)).") } // Prints "The point is at (1, 2)."
参考
https://docs.swift.org/swift-book/ReferenceManual/Patterns.html