[Swift] Pattern 과 Pattern Matching
01 Jul 2019 |
A pattern represents the structure of a single value or a composite value.
contents
- for destructing values
- for full pattern matching
- Where - 패턴과 결합하여 조건 추가하기
For Destructing Values - 값 추출하는 패턴
Wildcard Pattern
underscore _
for _ in 1...10 {
// do something ten times
}
Identifier Pattern
값을 변수나 상수 이름에 연결짓는 것
let age = 27
Value-Binding Pattern
Bind : v. 결합하다, 묶다
패턴에 맞는 값을 상수나 변수 이름에 연결짓는 것
let point = (2, 4)
switch point {
case let (x, y): //(let x, let y) 도 같은 의미
print("point: \(x), \(y)")
}
switch point {
case (let i, _):
print("\(i)")
}
switch point {
case(_, var j):
j += 10
print("move point up \(j)")
}
Tuple Pattern
let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]
// This code isn't valid.
// because the element - in the tuple pattern (x, 0) is an expression pattern
for (x, 0) in points {
/* ... */
}
괄호안에 element 가 하나인 경우는 tuple pattern 이 적용 안됨.
다음 세개는 다 동일한 의미 (equivalent)
let a = 2
let (a) = 2
let (a) : Int = 2
For Full Pattern Matching
Enumeration Case Pattern
switch
문 만 case 를 쓸 수 있는게 아니다!
If
, while
, guard
, for-in
구문 안에서도 case 조건 사용할 수 있다!
let aString = "ABC"
if case "ABC" = aString { // }
enum Dish {
case pasta(taste: String)
case chicken(withSauce: Bool)
case airRice
}
var dishes = [Dish]()
var myDinner : Dish = .pasta(taste: "cream")
dishes.append(myDinner)
if case .pasta(let taste) = myDinner { }
myDinner = .chicken(withSauce: true)
dishes.append(myDinner)
while case .chicken(let sauced) = myDinner {
break
}
myDinner = .airRice
dishes.append(myDinner)
if case .airRice = myDinner { }
for dish in dishes {
switch dish {
case let .pasta(taste): print(taste)
case let .chicken(sauced): print(sauced ? "양념" : "후라이드")
case .airRice: print("공기밥")
}
}
Optional Pattern
let someOptional: Int? = 42
// Match using an enumeration case pattern.
// optional은 enum 으로 구현되어있음 .some(Wrapped), .none
if case .some(let x) = someOptional {
print(x)
}
// Match using an optional pattern.
if case let x? = someOptional {
print(x)
}
optional value로 구성된 배열이 for 반복문 돌 때, nil 아닌 값만 수행되도록 하는 방법
let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
// Match only non-nil values.
for case let number? in arrayOfOptionalInts {
print("Found a \(number)")
}
// Found a 2
// Found a 3
// Found a 5
Type Casting Pattern
is
type
pattern as
type
Expression Pattern
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."
infix operator ~=
: pattern match (Precedence group -comparison Precedence)
~=
operator를 overloading 해서 expression matching behavior 커스텀하기
// 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)."
Where - 패턴과 결합하여 조건 추가하기
let tuples = [(1,2), (1,-1), (1,0), (0,2)]
for tuple in tuples {
switch tuple {
case let (x,y) where x == y: print("same")
case let (x,y) where x == -y: print("minus")
case let (x,y) where x>y: print("x is bigger than y")
case (1, _): print("x=1")
default: print("\(tuple.0),\(tuple.1)")
}
}
let arrayOfOptionalInts : [Int?] = [nil, 2, 3, nil, 5]
// nil 이 아닌 element 중에 2보다 큰 것
for case let number? in arrayOfOptionalInts where number > 2 {
print ("Found a\(number)")
}
//Found a 3
//Found a 5
protocol SelfPrintable {
func printByMyself()
}
struct Person : SelfPrintable { }
extension Int: SelfPrintable { }
extension String: SelfPrintable { }
extension SelfPrintable where Self: BinaryInteger, Self: Comparable {
func printByMyself() {
print("BinaryInteger, Comparable 만족하는 경우만 확장")
}
}
extension SelfPrintable {
func printByMyself() {
print("그외 나머지 경우 확장")
}
}
Int(10).printByMyself()
String("hello").printByMyself()
Person().printByMyself()
//BinaryInteger, Comparable 만족하는 경우만 확장
//그외 나머지 경우 확장
//그외 나머지 경우 확장
Reference
- https://outofbedlam.github.io/swift/2016/04/04/PatternMatching/
- https://docs.swift.org/swift-book/ReferenceManual/Patterns.html#
- https://alisoftware.github.io/swift/pattern-matching/2016/03/27/pattern-matching-1/ (유용한 패턴 매칭 예시)
- https://alisoftware.github.io/swift/pattern-matching/2016/03/30/pattern-matching-2/
- https://alisoftware.github.io/swift/pattern-matching/2016/04/24/pattern-matching-3/