以前の記事でKotlinで代数的データ型(Algebraic Data Type, ADT)とパターンマッチングの使い方を確認した。同様にSwiftでも確認する。なお本記事で使っているSwiftのバージョンは5.9である。
直和型 Sum Type
直和型にはenumを使う。
enum MusicGenre { case rock case pop case jazz case classic } enum YearsActive { case stillActive(_ start: Int) case activeBetween(_ start: Int, _ end: Int) }
直積型 Product Type
直積型にはstruct を使う。
typealias Location = String struct Artist { let name: String let genre: MusicGenre let origin: Location let yearsActive: YearsActive }
パターンマッチング
パターンマッチングにはswitchを使う。switch は網羅的でないとコンパイルエラーになる。
func prettyPrint(_ artist: Artist) -> String { // Note: switch must be exhaustive switch artist.yearsActive { case .stillActive(let start): return "\(artist.name) (\(start) - )" case .activeBetween(let start, let end): return "\(artist.name) (\(start) - \(end))" } }
以下は filter の中で使う例だ。以下の例なら、switchではなくifやguard を使っても同様の処理が書けた。
なおSwiftではif/switch/guardは文である。式になっている言語ほうが好みではある。
let stillActiveArtists = artists.filter { artist in // switch を使う場合 // switch artist.yearsActive { // case .stillActive: // return true // default: // return false // } // if を使う場合 // if case .stillActive = artist.yearsActive { // return true // } // return false // guard を使う場合 guard case .stillActive = artist.yearsActive else { return false } return true } print("# Still Active Artists") stillActiveArtists.forEach { artist in print(artist.name) }
まとめ
- Swiftで直和型は enum, 直積型は struct を使うことで実現できる。
- 直和型に対する パターンマッチングは switch を使うことで実現できる。場合によってはif や guard を使ってもよい。