Pattern Matching in an if Statement
Let’s say we have a simple enum
like this:
enum State<T> {
case Waiting
case Done(result: T)
}
And we want to do something when we have something the .Waiting
state.
The Wrong Approach
My first instinct was to write it like this:
let state = State<String>.Waiting // so we have something to work with in the Playground
if state == .Waiting {
print("do something")
}
But that didn’t work because it said error: type of expression is ambiguous
without more context
, because it can’t determine the generic type of T
there
(even though we’re not doing anything with the .Done
case, which is where the
associated value of type T
actually is). And even if we explicitly tell it
the generic type (which would be annoying to do in practice):
if state == State<String>.Waiting {
print("do something")
}
It still doesn’t work (error: binary operator '==' cannot be applied to two
'State<String>' operands
) because State
is not Equatable
. And we don’t
want to make it be Equatable
just for this, especially because then we’d have
to constrain T
to be Equatable
. Ugh.
The Proper Solution
Stepping back, what we’re trying to do is see if something is in the .Waiting
case, not check for exact equality. That’s what pattern matching is for. So
what we really want is to do this:
if case .Waiting = state {
print("do something")
}
That’s it. Nothing major here – just another small detail on the way to a more Swiftier way of thinking.