Swift Delight: guard

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.

  1. Arbitrary pattern matching outside of switch is performed with if case, so the full form of if let foo = maybeFoo is if case .some(let foo) = maybeFoo, sugared to if case let foo? = maybeFoo↩︎