-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Swiftabout Swiftabout Swift
Description
Pattern matching with ~= operator
패턴매칭에 숨겨진 operator 인 ~= 의 개념과 오버로드를 통한 적용사례들을 다룹니다.
conception
swift는 특정 패턴을 검사할 수 있는 패턴 매칭 문법을 제공합니다.
패턴 매칭이란 어떤 변수 또는 조건식이 만족하는 경우의 수에 따라 다르게 동작하도록 하는 것을 말한다.
주로 쓰이는 곳은 switch 문입니다.
struct Icecream {
let name: String
let price: Int
let isSour: Bool
}
let myIcecream = Icecream(name: "very strawberry", price: 3300, isSour: true)
switch myIcecream.isSour {
case true:
print("\(myIcecream.name) is sour taste")
case false:
print("\(myIcecream.name) is Non sour taste")
}위 예시코드가 실행되면 콘솔창에 very strawberry is sour taste 가 출력됩니다.
어떻게 위와 같이 일치하는 케이스 별로 처리를 해주는 걸까요?
swift는 아래와 같은 ~= operator를 사용해서 처리합니다. 다양한 타입으로 오버로드가 가능하며, 이 연산자를 잘 사용하면 원하는 다양한 패턴매칭 처리를 해줄 수 있습니다.
func ~= (pattern: Bool, value: Bool) -> Bool {
return pattern == value
}예시로 가격을 가격대로 구분하여 출력해야 한다고 가정합시다.
extension Icecream {
static func ~= (range: ClosedRange<Int>, icecream: Icecream) -> Bool {
return range.contains(icecream.price)
}
}~= 연산자를 위와 같이 오버로드 해줍니다.
switch myIcecream {
case 1000...2000:
print("1000원대 입니다.")
case 2000...3000:
print("2000원대 입니다.")
case 3000...4000:
print("3000원대 입니다.")
default:
print("가격대를 알 수 없습니다.")
}그리고 위 switch문을 실행하면 3000원 입니다 가 출력됩니다.
Limit
아쉽게도 튜플형태을 사용해서 전체를 비교하는 것은 불가능니다.
static func ~= (pattern: (name: String, price: Int, isSour: Bool), icecream: Icecream) -> Bool {
return pattern.name == icecream.name && pattern.price == icecream.price && pattern.isSour == icecream.isSour
}
switch myIcecream {
case ("very strawberry", 3300, true):
print("This is my icecream!")
default:
print("Not mine")
}이런 도전(?)을 하면 Tuple pattern cannot match values of the non-tuple type 'Icecream' 라는 컴파일 에러가 발생합니다.
Use case
struct Regex {
let pattern: String
static let email = Regex(pattern: "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}")
static let phone = Regex(pattern: "([+]?1+[-]?)?+([(]?+([0-9]{3})?+[)]?)?+[-]?+[0-9]{3}+[-]?+[0-9]{4}")
}
extension Regex {
static func ~=(regex: Regex, text: String) -> Bool {
return text.range(of: regex.pattern, options: .regularExpression) != nil
}
}
let email = "[email protected]"
switch email {
case Regex.email: print("email")
case Regex.phone: print("phone")
default: print("default")
}이렇게 정규표현식을 통한 검사 및 분류를 할 때 유용하게 쓰일 수 있다고 합니다.
[inspired article
Link 🔗
clsoft
Metadata
Metadata
Assignees
Labels
Swiftabout Swiftabout Swift