In this short bit, we want to decide whether a string is a phone number or an email address and create a value from this enum based on a string. We further created the two regexes to detect the different types - they may not be perfect, but this isn't the focus of this bit.
enum ContactPoint {
case phoneNumber(String)
case emailAddress(local: String, domain: String)
}
let phoneNumberRegex = /^\+?(\d{1,4})[\s\-\.]?(?:\(?(\d{1,4})\)?[\s\-\.]?)?([\d\s\-\.]{4,})$/
let emailRegex = /^(?<local>[A-Za-z0-9._%+-]+)@(?<domain>[A-Za-z0-9.-]+\.[A-Za-z]{2,})$/
let string = "+1 (555) 123-4567"
Unfortunately, regex pattern matching support for switch-case statements isn't available in Swift. I could imagine a syntax like this:
let result: ContactPoint? = switch string {
case phoneNumberRegex as match:
.phoneNumber(string)
case emailRegex as match:
.email(local: match.local, domain: match.domain)
default:
nil
}
Something very similar to this is possible by overriding the ~= operator, but it is limited to matching and you couldn't get the output without performing the match again. With the help of the last extension in the Swift file, we can write:
let result: ContactPoint? = switch string {
case phoneNumberRegex:
.phoneNumber(string)
case emailRegex:
// match doesn't exist here though, so we would need to rewrite the following line
.email(local: match.local, domain: match.domain)
default:
nil
}
At the moment, Swift supports if-let chaining to handle this case, which may not be the most elegant.
let result: ContactPoint? = if let match = try? phoneNumberRegex.wholeMatch(in: string) {
.phoneNumber(string)
} else if let match = try? emailRegex.wholeMatch(in: string) {
.emailAddress(local: String(match.local), domain: String(match.domain))
} else {
nil
}
With the code in the Swift file, you can write code like this to solve this issue:
let result: ContactPoint? = string.wholeMatch(
phoneNumberRegex.transform { _ in
.phoneNumber(string)
},
emailRegex.transform { match in
.emailAddress(local: String(match.local), domain: String(match.domain))
}
)