Chapters

Hide chapters

Swift Apprentice: Beyond the Basics

Second Edition · iOS 18 · Swift 6 · Xcode 16.2

Section I: Beyond the Basics

Section 1: 13 chapters
Show chapters Hide chapters

4. Pattern Matching
Written by Ehab Amer

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In this chapter, you’ll learn about proper golf attire: How to pair a striped shirt with plaid shorts:

No, just playing! This is not your grandfather’s pattern matching.

You’ve already seen pattern matching in action. In “Swift Apprentice: Fundamentals - Chapter 4: Advanced Control Flow”, you used a switch statement to match numbers and strings in different cases. That’s a simple example, but there’s a lot more to explore on the topic.

You’ll dive deep into the underlying mechanisms and understand more about how the Swift compiler interprets the code you type.

Swift is a multi-paradigm language that lets you build full-featured, production-ready, object-oriented software. The designers of Swift borrowed some tricks from more functional style languages like Haskell and Erlang.

Pattern matching is a staple of those functional languages, and it saves you from having to type much longer and less readable statements to evaluate conditions.

Suppose you have a coordinate with x-, y-, and z- axis values:

let coordinate = (x: 1, y: 0, z: 0)

Both of these code snippets will achieve the same result:

// 1
if (coordinate.y == 0) && (coordinate.z == 0) {
  print("along the x-axis")
}

// 2
if case (_, 0, 0) = coordinate {
  print("along the x-axis")
}

The first option digs into the internals of a tuple and has a lengthy equatable comparison. It also uses the logical && operator to ensure both conditions are true.

The second option, using pattern matching, is concise and readable.

The following sections will show you how — and when — to use patterns in your code.

Introducing Patterns

Patterns provide rules to match values. You can use patterns in switch cases, as well as in if, while, guard, and for statements. You can also use patterns in variable and constant declarations.

Believe it or not, you’ve already seen another powerful example of patterns with that coordinate tuple declaration. You construct a tuple by separating values with commas between parentheses, like (x, y, z). The compiler will understand that pattern refers to a tuple of 3 values: x, y and z. Tuples have the structure of a composite value.

Single values also have a structure. The number 42 is a single value and, by its very nature, identifiable.

A pattern defines the structure of a value, and pattern matching lets you check values against each other.

Note: The structure of a value doesn’t refer to the struct type. They are different concepts, even though they use the same word. It could be a symptom of the paucity of language!

Basic Pattern Matching

In this section, you’ll see some common uses for pattern matching.

if and guard

You’ve used if and guard statements for flow control. You can transform them into pattern-matching statements using a case condition. The example below shows how you use an if statement with a case condition:

switch

If you care to match multiple patterns, the switch statement is your best friend.

Mini-exercise

Given the population of a group, write a switch statement that prints out a comment for different group sizes: single, a few, several and many.

for

A for loop churns through a collection of elements. Pattern matching can act as a filter:

Patterns

Now that you’ve seen some basic pattern-matching examples, let’s see more patterns you can match.

Wildcard Pattern

Revisit the example you saw at the beginning of this chapter, where you wanted to check if a value was on the x-axis for the (x, y, z) tuple coordinate:

Value-binding Pattern

The value-binding pattern sounds more sophisticated than it turns out to be in practice. You simply use var or let to declare a variable or a constant while matching a pattern.

Identifier Pattern

The identifier pattern is even more straightforward than the value-binding pattern. The identifier pattern is the constant or variable name itself; in the example above, that’s the x in the pattern. You’re telling the compiler, “When you find a value of (something, 0, 0), assign the something to x.”

Tuple Pattern

You’ve already been using another bonus pattern — did you recognize it? The tuple isn’t just a series of comma-separated values between parentheses: it’s comma-separated patterns. In the example tuple pattern, (something, 0, 0), the interior patterns are (identifier, expression, expression).

Enumeration Case Pattern

In “Swift Apprentice: Fundamentals - Chapter 16: Enumerations”, you saw how you could match the member values of an enumeration:

Mini-exercise

In “Swift Apprentice: Fundamentals - Chapter 16: Enumerations”, you learned that an optional is an enumeration under the hood. An optional is either .some(value) or .none. You just learned how to extract associated values from optionals.

Optional Pattern

Speaking of optionals, there is also an optional pattern. The optional pattern consists of an identifier pattern followed immediately by a question mark. You can use this pattern in the same places you can use enumeration case patterns.

“Is” Type-casting Pattern

Using the is operator in a case condition, you check if an instance is of a particular type. An example of when to use this is parsing through a JSON export. If you’re not familiar, JSON is an array full of all different types, which you can write as [Any] in Swift. Web APIs and website developers make use of JSON a lot.

“As” Type-casting Pattern

The as operator combines the is type casting pattern with the value-binding pattern. Extending the example above, you could write a case like this:

Advanced Patterns

You’ve blazed through all the above patterns! What you’ve learned so far in this chapter will carry you quite far as a developer. In the upcoming section, you’ll learn additional modifier tricks to consolidate your code.

Qualifying With where

You can specify a where condition to further filter a match by checking a unary condition in-line:

Chaining With Commas

Another thing you learned was how to match multiple patterns in a single-case condition. Here’s an example similar to what you saw previously:

Custom Tuple

This chapter showed how a tuple pattern could match a three-dimensional coordinate (x, y, z). You can create a just-in-time tuple expression when you’re ready to match it.

Fun With Wildcards

One fun way to use the wildcard pattern is within the definition of a for loop:

Optional Existence Validate

In this code, you check to make sure user has a value. You use the underscore to indicate that, right now, you don’t care what value it contains.

Organize an if-else-if

In app development, views are rectangles. Here’s a simplified version:

Programming Exercises

As you develop confidence with Swift, you may find yourself applying for a job where you’d use Swift at work. Hiring interviews have some classic questions like the Fibonacci and FizzBuzz algorithms. Pattern matching can come in handy for both of these challenges.

Fibonacci

In the Fibonacci sequence, every element is the sum of the two preceding elements. The sequence starts with 0, 1, 1, 2, 3, 5, 8 …

FizzBuzz

In the FizzBuzz algorithm, your objective is to print the numbers from 1 to 100, except:

Expression Pattern

With all the pattern-matching skills you’ve developed, you’re finally ready to learn what’s underneath the hood. The expression pattern is simple but, oh, so powerful.

Overloading ~=

You can overload the ~= operator to provide a custom expression matching behavior. You’ll implement a pattern match between an array and an integer to check if the integer is an array element. A value of 2 should match the pattern [0, 1, 2, 3]. With the standard library, you’ll get an error on this code:

Challenges

Before moving on, here are some challenges to test your knowledge of pattern matching. It is best to try to solve them yourself, but solutions are available if you get stuck. These came with the download or are available at the printed book’s source code link listed in the introduction.

Challenge 1: Carded

Given this code, write an if statement that shows an error if the user is not yet 21 years old:

Challenge 2: Planets With Liquid Water

Given this code, find the planets with liquid water using a for loop:

Challenge 3: Find the Year

Given this code, find the albums that were released in 1974 with a for loop:

Challenge 4: Where in the World

Given the following code, write a switch statement that will print out whether the monument is located in the northern hemisphere, the southern hemisphere, or on the equator.

Key Points

  • A pattern represents the structure of a value.
  • Pattern matching can help you write more readable code than the alternative logical conditions.
  • Pattern matching is the only way to extract associated values from enumeration values.
  • The ~= operator is used for pattern matching, and you can overload it to add your own pattern matching.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now