モードマッチング第2弾:メタグループ、range、タイプ
6680 ワード
作者:Olivier Halligon,原文リンク,原文日付:2015-03-30訳者:小鍋;校正:saitjr;下書き:shanks
前の論文では,
メタグループのパターンマッチング
Swiftでは,
実際、
これは、複数のデータを1つのメタグループに組み合わせるだけで、複数のデータを一度に一致させることができることを意味します.たとえば、
前の文書で使用した
Caseは順番に判断しています
さらに、
これは、上記のコードにおいて、座標が
文字列と文字
なぜメタグループに止まるのですか?Swiftでは、文字列や文字など、多くのオリジナルタイプを一致させるために
カンマで区切られた複数のモードを使用してマッチングを行うことができ、これらのモードに一致するマッチング(ここではすべてのアクセントアルファベットに一致する)が同じコードを実行することができます.これにより、多くの重複コードを書くことを避けることができます.
Range
Rangeはモードマッチングにも役立ちます.注意してください.
?
では、
を選択します.
これですべては順調ですが、私たちはもっと進むことができますか?答えはもちろん問題ありません.パターンマッチングを...タイプ上!
ここでは、3つの構造体を定義し、同じプロトコルを遵守します.
そして、
一方、
?注意:
次のステップ
次のセクションでは、パターンマッチングに直接使用できるカスタムタイプを作成する方法を学び、より多くの構文糖を探索し、は、 もちろん、この文字列の分析方法は最良ではなく、推奨に値するものではありません.Unicode文字やローカライズはこれよりずっと複雑だからです.このような機能は は、 .
本文はSwiftGG翻訳グループから翻訳して、すでに作者の翻訳の授権を得て、最新の文章は訪問して下さいhttp://swift.gg.
前の論文では,
switch
を用いて列挙を基本的なモードマッチングすることを見た.では、列挙を除く他のタイプに対してswitch
を使用してモードマッチングを行うとどうなるのでしょうか.メタグループのパターンマッチング
Swiftでは,
switch
はObjCのように整数または列挙のみをマッチングできるわけではない.実際、
switch
を使用して、メタグループを含む多くのタイプをマッチングすることができます(ただし、限定されません).これは、複数のデータを1つのメタグループに組み合わせるだけで、複数のデータを一度に一致させることができることを意味します.たとえば、
CGPoint
があり、この点が座標軸上にあるかどうかを確認したい場合は、switch
を使用して.x
と.y
のプロパティを一致させることができます.
let point = CGPoint(x: 7, y: 0)
switch (point.x, point.y) {
case (0,0): print("On the origin!")
case (0,_): print("x=0: on Y-axis!")
case (_,0): print("y=0: on X-axis!")
case (let x, let y) where x == y: print("On y=x")
default: print("Quite a random point here.")
}
前の文書で使用した
_
ワイルドカードと、4番目のcase
で使用した(let x, let y)
は、変数をバインドし、where
を使用して等しいかどうかを確認することができることに注意してください.Caseは順番に判断しています
さらに、
switch
は、case
モードで指定された順序で評価を判断し、最初に満たされたcase
に一致した後に飛び出すことに注意されたい.CとObjective-Cとは異なり、break
キーワード1を使用する必要はありません.これは、上記のコードにおいて、座標が
(0, 0)
であれば、最初のcase
に一致して"On the origin!"
が印刷され、(0, _)
と(_, 0)
が一致してもマッチングの条件に合致しないことを意味する.最初のマッチングの後に飛び出したからです.文字列と文字
なぜメタグループに止まるのですか?Swiftでは、文字列や文字など、多くのオリジナルタイプを一致させるために
switch
を使用することもできます.
let car: Character = "J"
switch car {
case "A", "E", "I", "O", "U", "Y": print("Vowel")
default: print("Consonant")
}
カンマで区切られた複数のモードを使用してマッチングを行うことができ、これらのモードに一致するマッチング(ここではすべてのアクセントアルファベットに一致する)が同じコードを実行することができます.これにより、多くの重複コードを書くことを避けることができます.
Range
Rangeはモードマッチングにも役立ちます.注意してください.
Range
は、T
タイプのstart
およびend
メンバーを含む汎用タイプであり、T
はForwardIndexType
でなければなりません.これには、Int
およびCharacter
を含む多くのタイプが含まれる.?
Range(start: 1900, end: 2000)
を使用してrangeを明示的に宣言してもよいし、シンタックスオペレータ..<
(最後の数end
を含まない)または...
(最後の数end
を含む)を使用してもよいので、上記のrangeを1900..<2000
と書くこともできます(さらに読みやすい)では、
switch
でどのように使用しますか?実はかなり簡単で、case
モードでrangeを使って値がこの範囲内に落ちているかどうかを判断します!
let count = 7
switch count {
case Int.min..<0: print("Negative count, really?")
case 0: print("Nothing")
case 1: print("One")
case 2..<5: print("A few")
case 5..<10: print("Some")
default: print("Many")
}
case
の中でInt
の整数値とRange
の値を混用していることがわかる.このような使用には問題はありません.私たちが可能なすべての状況をカバーすることを保証すれば.Int
は最も一般的なrangeタイプですが、他のForwardIndexType
タイプも使用できます.Character
!上に書いたコードを覚えていますか?句読点やA-Z
以外の文字に対しても「Consonant」と印刷されるという問題があります.この問題を解決しましょう2(小文字も追加しました):
func charType(car: Character) -> String {
switch car {
case "A", "E", "I", "O", "U", "Y", "a", "e", "i", "o", "u", "y":
return "Vowel"
case "A"..."Z", "a"..."z":
return "Consonant"
default:
return "Other"
}
}
print("Jules Verne".characters.map(charType))
// ["Consonant", "Vowel", "Consonant", "Vowel", "Consonant", "Other", "Consonant", "Vowel", "Consonant", "Consonant", "Vowel"]
を選択します.
これですべては順調ですが、私たちはもっと進むことができますか?答えはもちろん問題ありません.パターンマッチングを...タイプ上!
ここでは、3つの構造体を定義し、同じプロトコルを遵守します.
protocol Medium {
var title: String { get }
}
struct Book: Medium {
let title: String
let author: String
let year: Int
}
struct Movie: Medium {
let title: String
let director: String
let year: Int
}
struct WebSite: Medium {
let url: NSURL
let title: String
}
// And an array of Media to switch onto
let media: [Medium] = [
Book(title: "20,000 leagues under the sea", author: "Jules Vernes", year: 1870),
Movie(title: "20,000 leagues under the sea", director: "Richard Fleischer", year: 1955)
]
そして、
Medium
に対してswitch
のモードマッチングを使用して、Book
とMovie
に対して異なることをさせるにはどうすればいいのでしょうか.簡単で、パターンマッチングにas
とis
を使います!
for medium in media {
// The title part of the protocol, so no need for a switch there
print(medium.title)
// But for the other properties, it depends on the type
switch medium {
case let b as Book:
print("Book published in \(b.year)")
case let m as Movie:
print("Movie released in \(m.year)")
case is WebSite:
print("A WebSite with no date")
default:
print("No year info for \(medium)")
}
}
Book
およびMovie
で使用されるas
については、それらが特定のタイプであるかどうかを決定する必要があり、もしそうであれば、変換されたタイプを定数(let b
またはlet m
)に割り当てる必要があります.なぜなら、私たちは後でこの定数3を使用するからです.一方、
WebSite
についてはis
しか使用していません.medium
がWebsite
タイプかどうかを調べるだけです.定数に変換して保存していません(print
文で使用する必要はありません).これはcase let _as Website
を使用するのと少し似ています.Website
タイプであるかどうかだけに関心を持っており、オブジェクトの値は必要ありません.?注意:
swtich
マッチングでas
およびis
を使用する必要がある場合、ここではコード異臭が存在する可能性があります.例えば、上記の特定の例では、protocol Medium
にreleaseInfo: String { get }
属性を追加することは、switch
を使用して異なるタイプをマッチングするよりも良いです.次のステップ
次のセクションでは、パターンマッチングに直接使用できるカスタムタイプを作成する方法を学び、より多くの構文糖を探索し、
switch
文の外でパターンマッチングを使用する方法と、より複雑なマッチング式を参照します.待ちきれないでしょう.fallthrough
キーワードを使用して、評価判定を次のcase
に流すことができる.しかし、実際にこのキーワードを使うシーンは少なく、あまり遭遇しません.NSCharacterSet
を使用して、現在のNSLocale
がどのアルファベットを母音と定義しているか(「y」は母音ですか?「switch
式とよく似ていますが、Range
が特定のタイプに変換できる場合、それらはすべて1つの変数にバインドされます.しかし、モードマッチングではif let b = medium as? Book
ではなくmedium
を使用します.それらのメカニズムは似ているが、それらの意味は異なる(「タイプ変換を試み、失敗した場合はas
」vs「このモードがこのタイプに一致するかどうかを判断する」)本文はSwiftGG翻訳グループから翻訳して、すでに作者の翻訳の授権を得て、最新の文章は訪問して下さいhttp://swift.gg.