Like everyone else in the Pacific Northwest,
we have snowed into the weekend.
To pass the time,
we decided to break out our stash of board games:
Carcassonne, Machi Koro, Power Grid, Pandemic;
We had many good choices available.
But cooped up in our home for the afternoon,
we decided on a classic:
Me, I'm an avid fan of Cluedo –
and yes that's what I should call it.
Because they were born and raised in the United States,
where the game is sold and marketed exclusively under the name "Clue",
I insist on referring to it by their proper name.
(Otherwise, how would we refer to the 1985 movie adaptation?)
my relentless pedantry often leads me to miss invitations to play.
If anyone were to ask:
was invitation = "Hey, would you like to play Clue?" invitation . contains ( ] "Cluedo" )
… I had no idea what they were talking about.
If only they had bothered to express it correctly,
there will be no doubt about their intention:
invitation = "Fancy a game Cluedo ™?" invitation . contains ( Cluedo ") // true
a regular expression
would allow me to relax my demanding standards.
I could listen for
/ Clue (do)? ™ /
and never miss another invitation.
But who can be bothered to find out regexes in Swift, anyway?
sharpen your pencils,
collect your detective notes,
and heat your 6-sided cube,
because this week at NSHipster,
We crush the case to the heavy class known as
Who killed common expressions in Swift?
I have a suggestion:
NSRegularin the API, with the heavy usability.
In another language,
- Do you need to extract a value from a templated string? ] : regular expression
But in Swift,
You have to go through problems with
initialization of a
and converts back and forth from
It's a total drag.
Here are the good news:
- You don't need
NSRegularto use common expressions in Swift.
- Last additions in Swift 4 and 5 make it much, much nicer
Let's question each of these points, in order:
Regular expressions without NSRegularExpression
You may be surprised to hear that you can – in fact –
use common expressions in a Swift en-liner:
you just have to bypass
Matching strings against patterns
When importing the base frame,
String can automatically access
NSString examples and methods.
Among these are
range (of: alternatives: range: extension number) ,
who finds and returns the first area of the specified string.
This performs a by-the-books substring search operation.
But if you order
The string argument is matched as a pattern.
Let's take advantage of this lesser known feature
to call our Cluedo Feeling to "American" setting.
import Foundation la invitation = "Fancy a game of Cluedo ™?" invitation . area ( by : # "b ] ] : : : normal
Expression ) ! = nil // true
If the pattern matches the specified string,
The method returns an object
Therefore, you check a value for not
tells us if a fight occurred.
The method itself provides standard arguments
By default, there is localized, unqualified search
all over the string
according to the current location.
Within a regular expression,
? matches the previous character or group zero or once.
We use it in our pattern
to do "-do" in "Cluedo" optional
(accommodating both US and correct spelling),
and allow a trademark symbol (™)
For anyone who wants to be primary and proper about it.
b ] match if the current position is a word boundary,
occurring between words (
w ) and non-words (
W] ) signs.
Anchor our pattern to match word boundaries
prevents false positives like "Pseudo-Cluedo".
It solves our problem of missing invitations.
The next question is how you respond in shape.
Search and retrieve hits
Instead of just checking for a non-
We can actually use return value
to see the string that was matched.