Whilst working on an iOS app, I was able to really jump into some Swift 3 features that were very new to me. Swift 3 has so many advantages over Objective-C but the one I am most impressed with is pattern matching.
Having dabbled a bit with Erlang and other functional programming languages in the past I can immediately see the benefits of this functional paradigm within Swift. It is rather advantageous because Swift now allows us to solve problems perhaps beter suited to functional programming languages (at least where pattern matching is concerned), and we may take examples from these other language to adapt them to work with Swift. So without further ado, lets talk about pattern matching.
The Model
Say you are modelling your favourite burger. Here’s
mine.
Each topping could be represented as a separate case within an enum
.
You get the idea. Add whatever toppings take your fancy.
The Humble Switch
In essence we have been using very basic pattern matching for a long time in languages such as Objective-C, C, Java, and many others through the form of switch statements. Here we tend to match strings with other strings or integers with other integers. But now we can take the humble switch statement and put it on steroids.
Using pattern matching switch statements can be used to match more complex structures containing placeholder variables, and bind these variables to real values if they match:
When the BurgerTopping
instance matches one of the cases, lets take the
second case as an example, then a new variable type
is created and the
associated value is bound to this variable.
Notice also the use of the wildcard pattern _
in the first case, which
indicates the presence of a variable but we don’t really care what it is. In
the above code I have used it in place of the seeds value. This is because I
don’t intend on using it in the proceeding statement.
Also note the fourth and fifth cases where no variables have been bound.
Pickle
and Tomato
have no associated values so we don’t need to add the
let
keyword. Furthermore if we were to write case let .Bun(_, _)
this would
be equivalent to case .Bun
as we dont need to bind any values.
Where and Fixed Values
As you can see there are a few way in which pattern matching can be made useful
for this use case. The BurgerTopping
s could be made a lot more complex or you
could be modelling something entirely different (i.e. a signup form where each
cell in a tableview could be represented).
But we can go further. Where I had included a wildcard in place of the seeds
value I now want to have a separate case for when seeds is either true
or
false
. We can do this with the where
clause. This is added to the end of a
case as shown below:
Here the first case will match with a Bun
where its seeds value is equal to
true
, whereas the seconds case will match with a Bun
where its seeds value
is equal to false
. Of course this is a very trivial equality whereby the
value can only ever be true
or false
and can alternatively be written with
Fixed Values:
This does the exact same thing as the first case except instead of using
where
I have explicitly attempted to match a constant value.
If and Guard Case
The switch statement is not the only to benefit from pattern matching. It may
also be used with if case
and guard case
. Below is a reimplementation of
the switch statement we have been using:
You may notice this is more verbose than the switch case scenario, due mostly
to curly braces and newlines, but yields the exact same results. Writing if
case let x = y { ... }
is strictly equivalent to writing switch y { case let
x: ... }:
; it’s just a more compact syntax useful when you only want to match
against one case as opposed to a switch which is more appropriate to multiple
case matching.
Take note that the where
clause here is represented by a single comma,
creating a multi-clause conditional statement.
What Else?
Beyond the control flow constructs mentioned above, pattern matching can also
be used with for case
and types. I have not yet needed to use these features
and may write about them in a future post. Until then I am going to continue to
altering my development habits to accommodate this functional pattern.
External Resources
- Patterns. See developer.apple.com.
- Match Me if you can: Swift Pattern Matching in Detail. See appventure.me.