Swift Delight: guard
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 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.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
switch
is performed withif case
, so the full form ofif let foo = maybeFoo
isif case .some(let foo) = maybeFoo
, sugared toif case let foo? = maybeFoo
. ↩︎