Coding Explorer Blog

Exploring how to code for iOS in Swift and Objective-C

  • Home
  • Apps
  • About
  • Contact

Pattern Matching in Swift

Xcode 11.6 Swift 5.2.4

Last updated on August 12, 2020

Pattern Matching in Swift

Pattern matching is a staple of functional languages.  At its core, Swift is primarily an object-oriented language, like Objective-C is.  However, there are many advantages to the way more functional style languages like Haskell and Erlang do things that the designers of Swift decided to include.  Pattern matching in particular, saves us having to type much longer, and less readable statements to do the same checks.

I mean, which is easier to read:

case (_, 0, 0):

or

if (someTuple.1 == 0) && (someTuple.2 == 0)

They both will find the same thing, but one can be used in a switch statement, and the other has to dig into the internals of a tuple and write a much longer looking comparison to 0 for each.  Not to mention the logical && there, to make sure both of them are true.

What Is a Pattern?

Now, firstly, what are we even referring to as a pattern?  These don’t look like repeated decorative designs to me.  I’m still pretty new to the concept in its more abstract form here, but based on what Apple’s iBook “The Swift Programming Language.” says:

A pattern represents the structure of a single value or a composite value.

That’s still pretty high level.  Let’s see if Wikipedia can help a bit more:

In computer science, pattern matching is the act of checking a given sequence of tokens for the presence of the constituents of some pattern.

Okay… that’s helping me a bit.  It seems that it is more talking about finding specific sequences of characters in the code to denote something.  That’s still not a particularly great way of putting it, but for instance, as we’ve seen in the earlier post Tuples in Swift: Create, Read, and Return, a Tuple is constructed by having comma separated values within parentheses, like (x, y, z).  The compiler should figure out by seeing that, that it is referring to a Tuple of 3 values, that are denoted as x, y, z.

In Swift, Patterns are used in variable/constant declaration, switch statement cases, catch blocks, and various conditionals (if, while, guard, and for-in statements).  However, only some of these patterns can be used the declaration and for-in statements:

Pattern Switch Cases Conditionals Declarations
Wildcard X X  X
Value-Binding X X X
Identifier X X X
Tuple X X X
Enumeration Case X X
Optional X X
“Is” Type-Casting X
“As” Type-Casting X
Expression X

Just from those names, you probably have a decent idea of what some of them are, and they may even seem familiar.  We’ve covered almost all of these to SOME extent before, but not from the perspective of being a pattern.

Let’s step through each of them:

Wildcard Pattern

This one is very simple.  This is the “Don’t care” style of pattern.  It just ignores a value, so if we wanted to check if say, a value was on the X axis, for our (x, y, z) tuple, but we don’t care what its actual value is, we could check for it with the pattern (_, 0, 0), saying that it has 0 for its y and z components, and so any x value will match.

Value-Binding Pattern

This is one of the patterns that sounds a lot more sophisticated than what it actually is.  This is, pretty much, referring to using “var” or “let” in order to declare a variable or a constant.  That doesn’t mean that it isn’t useful though, particularly when used in a Switch’s case statement.  There you can temporarily bind values to a variable or constant after matching it to a pattern, so a case like:

case let (x, 0, 0):

Would match for a value on the X axis, and then bind its X component to the constant named “x” so that it can be used in the case statement, like to print it, or perform a calculation.

Identifier Pattern

This one, if I understand it correctly, is even simpler than the Value-Binding Pattern.  This seems to basically be the variable name itself when binding a value with the value-binding pattern, so in the above example, the “x” is the pattern, basically saying, when you find something that is (something, 0, 0), put that something in “x”.  The reason it seems so intertwined, is because, as Apple says, the identifier pattern is a sub-pattern of the value-binding pattern.

Tuple Pattern

We already mentioned this somewhat, but the part that wasn’t mentioned was that a tuple isn’t just a series of comma-separated values between parenthesis, it’s actually comma-separated patterns.  As such, the identifier pattern (the “x” in the tuple), was one of the patterns it was matching to within the tuple pattern itself.

Enumeration Case Pattern

This appears to be exactly what it sounds like, it matches to the value of an enumeration in any conditional statement.  So if you have a cardinal direction enumeration, with the options North, South, East, and West, the enumeration case pattern is referring to how it will match to the specific enumeration value, so “case .North” will only match for the “.North” value of the enumeration.  This also extends to talking about Swift Enumerations that have associated values.  If that case does have an associated value, than a Tuple type of the number of elements associated with that Enumeration case must be appended to the enumeration case itself.  This used to just be used in Swift’s Switch statement, but in Swift 2 was broadened to all you to test for enumeration cases in pretty much any conditional (if, while, guard, and for-in).

“Is” Type-Casting Pattern

This refers to using the “is” operator in a switch statement’s case.  If the value being checked is a member of the type on the right side of the “is” operator, that pattern will be matched, and thus that case will execute.  So if we were stepping through an older NSArray that might have different types in it, we could check if the value we are looking at is a String with the case:

case is String:

Then that case would be run.  We wouldn’t have the value of the String though, that’s where the next pattern comes in.

“As” Type-Casting Pattern

Similarly, this is using the “as” operator in a switch statement’s case.  If the value being checked is a member of the type on the right side of the operator, it will cast that value and put it into the pattern on the left side, usually a “Value-Binding” pattern.  So for our above example, we could have a case statement like this:

case let text as String:
    print("The text we found was:  \(text)")

So if it found an object that was a string, it would cast the value to a Swift String, and then Value-bind it to the “text” identifier.

Expression Pattern

This one, at least to me, is less and more complicated than it sounds, simultaneously.  This refers to basically whether a Switch’s case statement matches a value (other than an enumerations available cases).  So, in our earlier example, of matching a Tuple pattern with (x, 0, 0), we know that internally, the Tuple is a comma-separated list of patterns.  We’ve already said that the “x” is a member of the identifier pattern.  The 0’s are members of the expression pattern, so the internal patterns to our Tuple there are (Identifier, expression, expression).

A bit more concretely, the expression pattern in Swift compares values with the ” ~= ” operator, and the match succeeds if that comparison results in a “true” value.  In many cases, particularly if the values compared are of the same type, it will just delegate to the more normal ” == ” operator to do the comparison.  You can override the ” ~= ” operator for your own class to customize how patterns match to your type if you wish.

For instance, it is actually used when checking if an Int value is within a range of Ints.  The range itself is certainly not an Integer, so we cannot just use the ” == ” operator.  However, one can conceptualize the idea of checking whether an Int is within the range, so we would need another comparison to perform that kind of check (which may be just a for-in loop under the hood for all I know), and that’s where the ” ~= ” operator comes in.  I don’t know if this operator has a name, but I’ll refer to it as the “equals-ish” operator.

Conclusion

Patterns in Swift are, at least to me, a strange mixture of being very powerful, simple, complex, and obvious, all at the same time.  They seem to basically be codification of some of the basics of the language, in such a way as to nail down exactly what they do for the compiler, and so that they can be used in other places that could take advantage of their capabilities, like a switch’s case statement.

I’m only scratching the surface of what they can do, but particularly since many of these patterns can themselves contain patterns, that’s where the real power comes in.  Combining them allows you very terse statements to express something that would normally need to be much longer, to get to a very specific combination of values.

I want this page to be a great place for people to come to understand what pattern matching in Swift means, so if you find any errors, or parts that were unclear, please let me know, so the article can be improved.

I hope you found this article helpful.  If you did, please don’t hesitate to share this post on Twitter or your social media of choice, every share helps.  Of course, if you have any questions, don’t hesitate to contact me on the Contact Page, or on Twitter @CodingExplorer, and I’ll see what I can do.  Thanks!

Sources

  • The Swift Programming Language – Apple Inc.
  • Pattern matching — Wikipedia

Filed Under: Swift Tagged With: Swift

Subscribe to the Coding Explorer Newsletter

* indicates required

Follow Us

Facebooktwitterrss

Recent Posts

  • Error Handling in Swift
  • Creating and Modifying a URL in your Swift App
  • Watch Connectivity in Swift — Application Context
  • watchOS Hello World App in Swift
  • API Availability Checking in Swift

Categories

  • Class Reference
  • General
  • Interface Builder
  • My Apps
  • Objective-C
  • Swift
  • Syntax
  • Tutorial
  • Uncategorized

Archives

  • May 2016
  • March 2016
  • February 2016
  • December 2015
  • July 2015
  • June 2015
  • April 2015
  • February 2015
  • January 2015
  • December 2014
  • November 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014
  • June 2014
  • May 2014
  • April 2014
  • March 2014
  • January 2014
  • November 2013
  • September 2013
  • August 2013
  • July 2013
  • Terms Of Use
  • Privacy Policy
  • Affiliate Disclaimer

Subscribe to the Coding Explorer Newsletter

* indicates required

Copyright © 2025 Wayne Media LLC · Powered by Genesis Framework · WordPress