Kwok Wen Jian - 2 years ago 59
Swift Question

# why does this variable have to be unwrapped?

I'm on the second lecture of Stanford's IOS 9 developer course. The lecturer is trying to build a calculator. I can't figure out two parts.
One:

``````if pending != nil {
accumulator = pending!.binaryFunction(pending!.firstOperand, accumulator)
pending = nil
``````

i understand that pending is an optional. but why is it that i still have to force unwrap it when I nested it in an "IF" statement that checks if it is nil or not?

The second part is:

``````  private struct PendingBinaryOperationInfo {
var binaryFunction: (Double, Double) -> Double
var firstOperand: Double
}
``````

why do the two variables need not have an initialiser? is it just because it is under "structure"?

The whole code is below. The two parts where i don't understand are found at the bottom of the chunk.

thanks a lot!

``````import Foundation

class CalculatorBrain
{
private var accumulator = 0.0

func setOperand(operand: Double) {
accumulator = operand
}

private var operations: Dictionary<String,Operation> = [
"e" : Operation.Constant(M_E),
"√" : Operation.UnaryOperation(sqrt),
"cos" : Operation.UnaryOperation(cos),
"×" : Operation.BinaryOperation({ \$0 * \$1 }),
"÷" : Operation.BinaryOperation({ \$0 / \$1 }),
"+" : Operation.BinaryOperation({ \$0 + \$1 }),
"−" : Operation.BinaryOperation({ \$0 - \$1 }),
"=" : Operation.Equals
]

private enum Operation {
case Constant(Double)
case UnaryOperation ((Double) -> Double)
case BinaryOperation ((Double, Double) -> Double)
case Equals
}

func performOperation(symbol: String) {
if let operation = operations[symbol] {
switch operation {
case .Constant(let value):
accumulator = value
case .UnaryOperation(let function):
accumulator = function(accumulator)
case .BinaryOperation(let function):
executePendingBinaryOperation()
pending = PendingBinaryOperationInfo(binaryFunction: function, firstOperand: accumulator)
case .Equals:
executePendingBinaryOperation()
}
}
}

private func executePendingBinaryOperation()
{
if pending != nil {
accumulator = pending!.binaryFunction(pending!.firstOperand, accumulator)
pending = nil
}
}

private var pending: PendingBinaryOperationInfo?

private struct PendingBinaryOperationInfo {
var binaryFunction: (Double, Double) -> Double
var firstOperand: Double
}

var result: Double {
get {
return accumulator
}
}
}
``````

``````if pending != nil {
accumulator = pending!.binaryFunction(pending!.firstOperand, accumulator)
pending = nil
``````

why is it that i still have to force unwrap it when I nested it in an "IF" statement that checks if it is nil or not?

Swift is a strongly typed language. In this case, `pending` is of type `PendingBinaryOperationInfo?`. Just because you checked it to make sure it isn't `nil` doesn't change the fact that `pending` is of type `PendingBinaryOperationInfo?`. You still need to unwrap it to access the `PendingBinaryOperationInfo` that is wrapped by the Optional.

The check for `nil` merely ensures that you can safely unwrap `pending` with `!` because you now know it won't crash due to `pending` being `nil`.

Sometimes, programmers will write this like this:

``````if let unwrappedPending = pending {
accumulator = unwrappedPending.binaryFunction(unwrappedPending.firstOperand, accumulator)
pending = nil
``````

This uses optional binding to unwrap `pending` and assign it to a new variable `unwrappedPending` that is of type `PendingBinaryOperationInfo` (which is not Optional).

Sometimes, you might also see this:

``````if let pending = pending {
accumulator = pending.binaryFunction(pending.firstOperand, accumulator)
pending = nil  // Oh, but this won't work because pending isn't optional
``````

In this case, a new variable `pending` which is of type `PendingBinaryOperationInfo` is created which hides the original `pending` variable. I personally don't like this form because it confuses the issue with 2 different variables of two different types with the same name. In this case, it wouldn't work anyway, because the author also wants to set `pending` to `nil`, and you no longer have access to the original optional `pending` inside the `if`.

The second part is:

``````private struct PendingBinaryOperationInfo {
var binaryFunction: (Double, Double) -> Double
var firstOperand: Double
}
``````

why do the two variables need not have an initialiser? is it just because it is under "structure"?"

Yes. For structures, Swift automatically generates an initializer for you that initializes all properties. You can see this initializer with Xcode's autocomplete feature by typing:

``````PendingBinaryOperationInfo(
``````

As soon as you type the `(`, the initializer will pop up as the suggested completion. Here it is in a Playground:

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download