Swift Pattern Matching Is Powerful

In Natasha The Robot’s weekly Swift newsletter, I caught a pretty awesome series of articles written by Olivier Halligon on Swift pattern matching. After reading this four-post series, my mind is sufficiently blown in thinking about all these new ways to use Swift pattern matching.

swift pattern matching
]4 Pattern matching in the real world.

Here are the articles:

According to Apple’s documentation on Swift Patterns:

A pattern represents the structure of a single value or a composite value. For example, the structure of a tuple (1, 2) is a comma-separated list of two elements. Because patterns represent the structure of a value rather than any one particular value, you can match them with a variety of values. For instance, the pattern (x, y) matches the tuple (1, 2) and any other two-element tuple. In addition to matching a pattern with a value, you can extract part or all of a composite value and bind each part to a constant or variable name.

Basically, this means that if you have a value like a struct, the struct can be represented by any number of “patterns” that generally describe the type. You can then use patterns in conditional checks to selectively filter for values that match the pattern.

Switches, Not Just Integers

From Olivier’s articles:

In Swift, you’re not restricted to use switch on integer values or enums like in ObjC. You can actually switch on a lot of stuff, including (but not restricting to) tuples.

This was an incredible discovery for me. It’s little nuggets of discovery like this that so easily slip through the cracks when learning new languages.

This Is Scary

Switch case statements are evaluated in order. This feels scary to me.

Here’s Olivier’s example:

let point = CGPoint(x: 7, y: 0)
switch (point.x, point.y) {
  case (0,0): print("On the origin!")      // 1
  case (0,_): print("x=0: on Y-axis!")     // 2
  case (_,0): print("y=0: on X-axis!")     // 3
  case (let x, let y) where x == y: print("On y=x")
  default: print("Quite a random point here.")

This gets my nerves going big time. You could easily inadvertently swap the order of lines 1, 2, and 3, with no compiler warning, and have vastly different functionality of your code. You MUST pair code like this with tests, or just avoid relying on the order of the cases altogether.

Exhaustive, no defaulting

One of the things I like best about Swift is how the language easily enables you to be totally explicit about how you intend for things to behave. switch statements are another example in that the compiler simply won’t let you write a switch statement there may be a condition that doesn’t match. Furthermore, I also like this advice from Olivier:

I strongly recommend you to not use default when possible, and instead make your switch exhaustive, this way if you happen to add a new value to your enum you’ll be forced to think about what to do with it instead of it being ignored or eaten up by the default without you realizing.

In other words, Command-Shift-F for “default” and inspect any switch statement you find that uses it, and do everything possible to refactor it out.

Your Own Objects

If you want to use Swift pattern matching on your own objects, just override the ~= operator as:

func ~= (lhs: Affine, rhs: Int) -> Bool

When doing that though, keep in mind this advice from Olivier:

Don’t mix up the parameters order: the first parameter of the infix ~= operator (commonly named lhs, for left-hand side) is the object you’re gonna use in your case statements. The second parameter (commonly named rhs for right-hand side) is the object you’re switch-ing over.

A Real World Example

A lot of this blog series focused on theoretical uses of value types like Movies or Books. I really like when Olivier brought it back to the real world, or at least my real world with an example of using guard case let for checking the HTTP response code for a remote API call.

Looking Forward

I’m really excited to find uses for Swift pattern matching in my own code now that I know all about it. I recommend Olivier’s full article series and guarantee that you’ll learn something along the way. It’s a concise read and won’t take much of your time. Come back and let me know what you learned.

Happy cleaning.