Swift delight: guard. I was never interested in `unless`; `if !foo` never bothered me. But you can’t negate pattern-matching in the same way, and Swift’s `if let` was a form of pattern-matching specific to Optional.— Jordan Rose (@UINT_MIN) September 29, 2021
Part of the Swift Regrets series.
I was never interested in
if !foo never bothered me. But you can’t negate pattern-matching in the same way, and Swift’s
if let was a form of pattern-matching specific to Optional.1 The problem with
if let was the increased nesting, when the else branch was probably just going to return some default value. An early-exit, except
if let kept it from being early.
The insight for
guard let was that in order to introduce names in the current scope, the
else branch had to leave the current scope. Everything else about
guard falls out from that. And it turns out
guard is great even without pattern-binding, because both the name and the leave-the-scope requirement make it clearer that this is some sort of pre-check, an exceptional case or a filter. Whereas both branches of an
if are equally valid, absent other info. There are people who don’t like early exits, but I think if you’re going to have them, calling them out with
guard makes them better. (Though if you end up with double negation in your conditions, maybe use
if instead even for an early exit.)
P.S. Why “guard”? It’s a compromise, trying to find a name that’s meaningful but also not too long. I think “ensure” might have been the other leading candidate? It’s been a long time.
Arbitrary pattern matching outside of
switchis performed with
if case, so the full form of
if let foo = maybeFoois
if case .some(let foo) = maybeFoo, sugared to
if case let foo? = maybeFoo. ↩︎