2

Sometimes, I want to use guard combined with let & where to simplify my code. But I wonder what's the priority of let and where. For example:

class Person {
    func check() -> Bool? {
        print("checking")
        return nil
    }
}

func test(dont: Bool) {
    let person = Person()
    guard let check = person.check() where dont else {
        print("should not check")
        return
    }
    print("result: \(check)")
}


test(false)

As you can see the console result, printed output are:

  • checking
  • should not check

For the condition of let check = person.check() where dont in guard <condition> else { } syntax, even the expression in where doesn't relate to the results of expression in let, Swift seems to execute let first then check where later. Sometimes in my code, let optional binding takes lots of calculation and where is only a simple condition without relying on let results, should I move the where out of guard? Or I'm wrong about the priority or let & where?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
bubuxu
  • 2,187
  • 18
  • 23

1 Answers1

5

You are right, in your Swift 2 code

guard let check = person.check() where dont else { }

the conditional binding let check = ... is checked first, and only if that succeeds, the boolean condition dont is checked. You can use

guard dont, let check = person.check() else { }

to check the boolean condition first.

This "asymmetry" in the syntax has been removed in Swift 3: All guard clauses are separated by commas and the where keyword is not used anymore. So you have

guard let check = person.check(), dont else { }
// or
guard dont, let check = person.check() else { }

The conditions are checked from left to right with short-circuiting, i.e. if one condition fails then the else-block is executed without checking the remaining conditions.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382