斯威夫特的iOS 9斯坦福课程 - 第1讲

时间:2015-08-05 16:11:54

标签: ios swift cs193p

我目前正在尝试完成iTunes U上的Swift课程,我们正在构建一个计算器。我无法理解部分代码。

我在下面添加了我认为与文件相关的代码。

这让我感到困惑:为什么操作(操作数)会计算UnaryOperation的值(即平方根)?我看到当调用CalculatorBrain类时,字典被初始化了,但是当我打印字典时,我得到的东西看起来像这样:[✕:✕, - : - ,+:+,⌹:⌹,√:√ ]。那么当我点击平方根按钮时,程序在何时/何时计算平方根?

Class CalculatorBrain
    {
    private enum Op: Printable
    {
    case Operand(Double)
    case UnaryOperation(String, Double -> Double)
    case BinaryOperation(String, (Double, Double) -> Double)

    var description: String {
        get {
            switch self {
            case .Operand(let operand):
                return "\(operand)"
            case .UnaryOperation(let symbol, _):
                return symbol
            case .BinaryOperation(let symbol, _):
                return symbol
            }
        }
    }
}

private var opStack = [Op]()

private var knownOps = [String: Op]()

init() {
    func learnOp(op: Op) {
        knownOps[op.description] = op

    }
    learnOp(Op.BinaryOperation("✕", *))
    learnOp(Op.BinaryOperation("⌹") { $1 / $0 })
    learnOp(Op.BinaryOperation("+", +))
    learnOp(Op.BinaryOperation("-") { $0 - $1 })
    learnOp(Op.UnaryOperation ("√", sqrt))

}

private func evaluate(ops: [Op]) -> (result: Double?, remainingOps: [Op])
{
    if !ops.isEmpty {
        var remainingOps = ops
        let op = remainingOps.removeLast()
        switch op {
        case .Operand(let operand):
        return (operand, remainingOps)
        case .UnaryOperation(_, let operation):
            let operandEvaluation = evaluate(remainingOps)
            if let operand = operandEvaluation.result {
                **return (operation(operand), operandEvaluation.remainingOps)**
            }
        // case.BinaryOperation(.....)
        }
    }
    return (nil, ops)
}

 func evaluate() -> Double? {
    let (result, remainder) = evaluate(opStack)
    return result
}

func pushOperand(operand: Double) -> Double? {
    opStack.append(Op.Operand(operand))
    return evaluate()
}

func performOperation(symbol: String) -> Double? {
    if let operation = knownOps[symbol] {
        opStack.append(operation)
    }
   return evaluate()
}

}

2 个答案:

答案 0 :(得分:1)

Op枚举实现了Printable协议,这意味着它具有description: String属性。当您打印Dictionary时,您将[String : Op]发送到println函数,然后尝试使用Op打印description

运算符描述与Dictionary中的键相同的原因是因为learnOp(op: Op)函数将键设置为op.descriptionknownOps[op.description] = op)< / p>

要查看此效果,您可以添加一个新的运算符learnOp(Op.UnaryOperation ("@", sqrt)),该@:@将在knownOps字典内打印为@。 (如果为evaluate()运算符添加新按钮,它也将执行平方根运算)

由于计算器是基于堆栈的,操作数会被推入,然后是操作。当evaluate(opStack)被调用时,它会调用evaluate(ops: [Op])来传递整个堆栈。

[ 4, 5, +, sqrt ]然后从堆栈中取出to项目,并在计算出操作数后计算函数。

举个例子,假设你想要calucalte sqrt(4 + 5)。

您可以将项目推送到堆栈,它看起来像:evaluate(ops: [Op])

然后sqrt看到+并使用递归调用评估操作数。然后,该调用将使用另外两个返回54的递归调用来评估ops: [4, 5, +, sqrt] // Returns sqrt(9) = 3 | ops: [4, 5, +] // Returns 4 + 5 = 9 ____|_____ | | ops: [4, 5] ops: [4] return 5 return 4

电话树看起来像这样:

evaluate() -> Double?

我强烈建议你在<!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> 函数上放一个断点,然后逐步执行程序,看看它在不同的操作数和操作中的位置。

答案 1 :(得分:0)

learnOp(Op.UnaryOperation ("√", sqrt))

sqrt是一个内置功能,所以你要教导计算器&#34;√&#34;意味着它应该执行sqrt操作。