Page 75 - can you help me understand the conditional binding?

#1

Hello,

I am very puzzled by this code:

var fahrenheitValue: Double?

var celsiusValue: Double? {
if let value = fahrenheitValue {
return (value - 32) * (5/9)
}
else {
return nil
}
}

So what I think is happening is that the variable celsiusValue is being defined as an optional double, and a piece of code is run which sets the celsiusValue at either nil (if fahrenheitValue is nil) or else returns (fahrenheitValue - 32) * (5/9). The test of whether fahrenheitValue is nil or not is:

if let value = fahrenheitValue.

But I don’t understand why this fails. We haven’t defined value in any code above this, so couldn’t value also be optional?

Thanks!

#2

Because an if-let statement is defined to work that way. You need to realize that an if-let statement is distinct from an if statement, and it operates differently. In an if-let statement, the variable on the left of the equals sign is a new variable that is local to (i.e. it can only be seen inside) the block that follows. If the variable on the right of the equals sign is nil, then the else clause executes (and if you try accessing the value variable inside the else clause, you will get an undefined error).

We haven’t defined value in any code above

And it wouldn’t matter if you had because the value variable that the if-let statement creates inside the block that follows is an entirely different variable. Here is an example of that:

var value: Int? = 1
var x: Double? = 5.25

if let value = x {
    print(value)   //5.25
    print(value.dynamicType)  //Double
}

print(value!)  //1
print(value.dynamicType)  //Optional<Int>

couldn’t value also be an optional

The type of the variable on the left of the equals sign depends only on the type of the variable on the right of the equals sign. The type of the variable on the left will be the type of the variable on the right with a “?” removed, so in the example the value variable will be type Double.

#3

Optional Binding
To conditionally bind the wrapped value of an Optional instance to a new variable, use one of the optional binding control structures, including if let, guard let, and switch.

if let starPath = imagePaths["star"] {
    print("The star image is at '\(starPath)'")
} else {
    print("Couldn't find the star image")
}
// Prints "The star image is at '/glyphs/star.png'"

see:

https://developer.apple.com/reference/swift/optional