1

Learning swift 3.1 by reading Language Guide (developer.apple.com). I learned that in swift the assignment operator (=) does not return a value. In control flow chapter got an example of guard statement:

func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }

    print("Hello \(name)!")

    guard let location = person["location"] else {
        print("I hope the weather is nice near you.")
        return
    }

    print("I hope the weather is nice in \(location).")
}

My question is if '=' operator does not return value then:

guard let name = person["name"] else {
    return
}  

How does guard determine name = person["name"] is true or false and depending on that go to else and return?

Hamish
  • 78,605
  • 19
  • 187
  • 280
MD TAREQ HASSAN
  • 1,188
  • 20
  • 46
  • 1
    Correct, `=` does not return any value. But the `person["name"]` returns an optional, so `guard let` is doing the optional binding of that value to the variable in question. So the `guard let` statement is saying "`guard` to ensure `person["name"]` returns a value and if so, set `name` variable to that unwrapped value". But, if not (i.e. if `person["name"]` returned `nil`), then it will perform what's in the `else` clause (e.g. `return` in this case) – Rob Apr 09 '17 at 14:10
  • @Rob, So for guard statement: `guard let ` condition (`name = person["name"]`) does not have to be true or false? – MD TAREQ HASSAN Apr 09 '17 at 14:46
  • 1
    @HassanMakarov It's not `guard let ` – it's `guard `. A `` can either be an expression evaluating to a `Bool`, an availability condition, a case condition, or in this case, an optional-binding condition – which usually has the syntax `let = `. This does *not* mean that it evaluates to a `Bool`. See [the grammar section of the language guide](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Statements.html#//apple_ref/swift/grammar/condition-list) if you want a more detailed breakdown. – Hamish Apr 09 '17 at 15:20
  • See [Optional Binding](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID333), which shows how this works with `if` statements, and it's the same idea with early-exit `guard`-`else` statements. – Rob Apr 09 '17 at 15:33

2 Answers2

5

The purpose of guard is to assert that a value is non-nil, and to guarantee exit of the current scope if it is. This allows the value to be used throughout the rest of your function and to allow your "golden path" to not be nested within several if-statements.

You can do something similar with an if-let syntax, but it provides no guarantees that the scope must be exited or provide that protected value outside of it's own scope.

guard let name = person["name"] else {
    return
}
// name available here!

vs

if let name = person["name"] {
    // name available here
} else {
    // name not available here
}

// name not available here either

All of this is based on whether the if/guard statements can guarantee the existence of a value, not on truthiness.

1

As @Hasmish pointed out, let name = person["name"] is a optional-binding-condition. It evaluates to true when the right side is not nil, and has a side effect of binding the wrapped value to the identifier on the left side.

The optional-binding-condition has no regard to whether the right hand side is true/false.

let optionalBool: Bool? = false
guard let bool = optionalBool else {
    fatalError("This will never be called, because `optionalBool` is not `nil`")
}

In fact, the right hand side doesn't even have to be a Bool, as you demonstrated.

Alexander
  • 59,041
  • 12
  • 98
  • 151