Swiftのパターンマッチングは、switch、ループ、およびif case構文を使用して値を優雅に抽出し、パターンと比較することを可能にします。重要な特徴は、値を比較するだけでなく、関連データを複雑な構造から抽出できることです。たとえば、関連値を持つ列挙型、オプショナル、またはタプルです。
case let演算子は、ネストされた値を抽出するために頻繁に使用されます。例:
enum Result { case success(value: Int) case failure(error: Error) } let result: Result = .success(value: 42) switch result { case .success(let value): print("成功: 値は \(value)") case .failure(let error): print("失敗: エラーは \(error)") }
コレクションを扱う際にもパターンマッチングを使うのが便利です。
let items: [Result] = [.success(value: 1), .failure(error: MyError()), .success(value: 42)] for case let .success(value) in items { print("見つかった値: \(value)") }
すべてのパターンが機能するわけではなく、構造体や列挙型が関連値がなく、Equatableの必要なサポートがない場合、動作しないことを思い出すことが重要です。また、経験の浅い開発者は、enumの全ケースを考慮することを忘れる可能性があります。
オプショナル値を扱う際のif let、guard let、if case letの違いは何ですか?それぞれどのような場合に好まれますか?
回答:
if letとguard letは、オプショナルからの値の安全な抽出に使用されます。if case letは、オプショナルだけでなく関連値を持つenumにも適用され、パターンマッチングの機能を拡張します。例:
let number: Int? = 42 if case let value? = number { print("値は \(value)") }
value?は、値がnilでない場合のみ抽出するパターンです。
物語
開発者は、switchでenumのすべてのcaseを実装しませんでした。enumに新しいcaseを追加すると、"安全性のため"にdefaultブランチを追加したため、サイレントエラーが発生しました。その結果、部分的なロジックが動作しなくなり、エラーはユーザーにのみ現れました。
物語
プロジェクトでは、
Result<T, Error>の配列を使用し、通常のループfor x in...で成功した値だけをフィルタリングしようとしました。これにより、型の手動チェックが発生し、条件に誤りがあったため、いくつかの成功が見逃されました。
物語
チームのメンバーの1人は、オプショナルに対する
if case letを知らず、常に二重チェックを行っていました:最初にif number != nil、次に"強制的なアンラップ"を通じて値を抽出しました。これにより、プロダクションでクラッシュが発生しました。