Can the switch case statement with a Swift regex literal expression be somehow modified to function OK?
Yes, a case let … where …
pattern with a /regex/
literal can be used. This approach can also be implemented in a way that expressly avoids potential ~=
ambiguities.
Discussion…
Match-Part-Or-Whole Example - A fundamental approach where the original regex pattern /^…$/
is used to match a entire line:
extension String {
func matchFirst(_ regex: Regex<Substring>) -> Bool {
// errors count as "not match"
(try? regex.firstMatch(in: self)) != nil
}
}
switch "---abc---" {
case let s where s.matchFirst(/^\w+$/):
print("entire line contains alphanumerics: '\(s)'")
case let s where s.matchFirst(/\w+/):
print("alphanumerics found in string: '\(s)'")
default:
print("no alphanumerics found")
}
Whole-Match-Only Example - A "whole match only" regex approach where a partial match is not possible:
extension String {
func matchWhole(_ regex: Regex<Substring>) -> Bool {
// errors count as "not match"
(try? regex.wholeMatch(in: self)) != nil
}
}
switch "---abc---" {
case let s where s.matchWhole(/\w+/):
print("all alphanumerics: '\(s)'")
//case partial match not available. whole or nothing.
default:
print("no match for /\\w+/")
}
I ended up using the "classic" Match-Part-Or-Whole Example approach instead of the Whole-Match-Only Example and func ~=
approaches for the following reasons:
func ~=
- could possibly be defined by Swift at some future time. Possible future confusion.
- Whole-Match-Only Example - does not support both partial and full matches. Less expressive.
- Match-Part-Or-Whole Example
- leaves
~=
undefined which allows for the possible future definition by Swift. Avoids possible future confusion.
- does support both partial and full matches. More expressive.
^…$
is expressly stated for a full line match. More readable.
Note: Extending String
with both convenience wrappers, such as matchFirst
and matchWhole
, can allow for either approach to be choosen at the point of use. This approach provides the following benefits:
- expressive
- co-locates both choices in the point-of-use autocompletion list
- avoids the conflict of one vs the other in the lower level extension
- does not presume any interpretation for the not-yet-officially-defined
~=
.
extension String {
func matchFirst(_ regex: Regex<Substring>) -> Bool {
// errors count as "not match"
(try? regex.firstMatch(in: self)) != nil
}
func matchWhole(_ regex: Regex<Substring>) -> Bool {
// errors count as "not match"
(try? regex.wholeMatch(in: self)) != nil
}
}
Historic Footnote
The ^
begin-anchor and $
end-anchor syntax has been part of Regular Expressions since the 1970s with qed
and ed
PDP-7 AT&T Bell Labs Unix editors.
QED Text Editor (1970 Bell Telephone Laboratories technical memorandum)

ed (see man ed
or info ed
on POSIX and Open Group compliant Unix-like systems)

See also man ed
and info ed
on modern BSD/Linux/Unix systems. It's still there.
The ^
begin-anchor and $
end-anchor syntax was also carried forward to other Regular Expression enabled software tools, such as sed
, g/re/p
global regular expression, Perl Compatible Regular Expressions (PCRE) library, and POSIX standard Basic Regular Syntax (BRE).
Thus seeing, reading, and writing ^
begin-anchor and $
end-anchor syntax can be natural (and even expected) for an experienced REGEX user. And, having /^.$/
implied and hidden for some compacted convience can reduce the REGEX expressive capability for an experienced REGEX user.