Как использовать литеральные регулярные выражения Swift в операторах шаблона switch case?
Как использовать литеральные регулярные выражения Swift в операторах шаблона switch case?
Основываясь на примерах из слайдов презентации WWDC 2022, ожидается, что следующее скомпилируется и запустится нормально:
import Foundation
import RegexBuilder
switch "abc" {
case /\w+/:
print("matched!")
default:
print("not matched.")
}
Однако возникает следующая ошибка:
Образец выражения типа
Regex<Substring>
не может соответствовать значениям типаString
Может лиswitch
case
оператор с литеральным выражением регулярного выражения Swift каким-то образом модифицируется, чтобы он функционировал нормально? Как можно использовать новые возможности регулярных выражений Swift 5.7 в операторе шаблона switch case?
2 ответа
Из того, что я нашел, "сопоставление с регулярными выражениями вswitch
оператор" не был реализован, потому что люди спорили о том, какой должна быть точная семантика. В случае, например,
switch "---abc---" {
case /\w+/:
print("foo")
default:
print("bar")
}
в какой ветке должен выполняться оператор switch? Должен ли он считаться совпадением только в том случае, если вся строка соответствует регулярному выражению, или этого достаточно только для совпадения подстроки переключаемой строки? Другими словами, этоwholeMatch
илиfirstMatch
? Смотрите больше обсуждения здесь.
В конце концов, они не смогли прийти к выводу, и
Предложение было принято с изменениями (на данный момент изменения должны быть включены в подмножество).
Итак~=
оператор не был добавлен дляRegex<Output>
, поэтому вы не можете использовать его в коммутаторе.
Вы можете добавить его сами, если хотите, если можете выбрать между двумя семантиками :) Например:
func ~=(regex: Regex<Substring>, str: String) -> Bool {
// errors count as "not match"
(try? regex.wholeMatch(in: str)) != nil
}
Можно ли каким-то образом изменить оператор switch case с литеральным выражением регулярного выражения Swift, чтобы он работал нормально?
Да, используйтеcase let … where …
подход с возможностью регулярных выражений, выпущенной, начиная с Swift 5.7.
Классический пример - "классический" пример регулярного выражения, где/^…$/
может использоваться для соответствия полной строке:
extension String {
func classic(_ regex: Regex<Substring>) -> Bool {
// errors count as "not match"
(try? regex.firstMatch(in: self)) != nil
}
}
switch "---abc---" {
case let s where s.classic(/^\w+$/):
print("entire line contains alphanumerics: '\(s)'")
case let s where s.classic(/\w+/):
print("alphanumerics found in string: '\(s)'")
default:
print("no alphanumerics found")
}
Пример полного совпадения — подход регулярного выражения «только полное совпадение», когда частичное совпадение невозможно:
extension String {
func whole(_ regex: Regex<Substring>) -> Bool {
// errors count as "not match"
(try? regex.wholeMatch(in: self)) != nil
}
}
switch "---abc---" {
case let s where s.whole(/\w+/):
print("all alphanumerics: '\(s)'")
default:
print("no match for /\\w+/")
}
В итоге я использовал подход «Классический пример» вместо примера «Только полное совпадение» иподходит по следующим причинам:
-
func ~=
- возможно, будет определен Swift в будущем. Возможная путаница в будущем. - Пример полного совпадения — не поддерживает как частичное, так и полное совпадение. Менее выразительный.
- Классический пример
- листья
~=
undefined, что позволяет возможное определение Swift в будущем. Избегает возможной путаницы в будущем. - поддерживает как частичные, так и полные совпадения. Более выразительный.
-
^…$
прямо указано для полного совпадения строк. Более читаемый.
- листья