Necessary to break up guard statements to prevent extra computations?

时间:2019-01-15 18:13:09

标签: swift

If certain guard statements are more important than others, is it necessary to break them up? For example:

guard let someProperty = someProperty,
    someProperty < someValue else {
        return
}

// if some property is OK, unwrap other properties

guard let anotherProperty = anotherProperty,
    let moreProperties = moreProperties else {
        return
}

The example above without question prevents any unnecessary unwrapping if someProperty does not meet the predicate. However, would the same amount of work be done if they were combined?

guard let someProperty = someProperty,
    someProperty < someValue,
    let anotherProperty = anotherProperty,
    let moreProperties = moreProperties else {
        return
}

Obviously the process will run from top to bottom, but does the machine run the entire guard and then assess completion or failure, or does the machine exit the guard at the first failed clause?

2 个答案:

答案 0 :(得分:3)

No it is not necessary to break up the statements.

You can easily check this by executing the following code:

var condition = false
func failingTest() -> Bool {
  fatalError("this should never execute")
}
guard condition, failingTest() else {
  print("Early exit")
  return
}
  • When this prints Early exit, you know that it didn't evaluate all the conditions of the guard before printing the early exit.
  • When this raises a fatal error, you know that it executed the failingTest even after it knew condition was false.

When executing this code snippet using Apple Swift version 4.2.1 we get Early exit so we know that Swift stops evaluating the guard conditions after the first condition that evaluates to false.

Normally you should be able to look up these kind of things in the language reference. But in this case, the answer to your question is not yet mentioned in the reference. Hopefully someone will add it in the future.

答案 1 :(得分:1)

The guard statement works as: if the first predicate is false it will not evaluate the next predicate(s).

In other words, you could consider the comma , of the guard statement as the same as the && operator. That's what we call it a lazy evaluation; If you checked how && works, you would notice that the rhs is an autoclosure returns a boolean but not a boolean, which means that it might be not even evaluated (in case of lhs parameter is false).

want to see more about autoclosure? check this out!

So for your case, you could combine all the predicates (which I think it would be more readable IMO) in one guard statement.