iOS 9 斯坦福课程 Swift - 第 1 讲
iOS 9 Stanford Course in Swift - Lecture 1
我目前正在努力完成 iTunes U 上的 Swift 课程,我们正在构建一个计算器。我无法理解部分代码。
我在下面添加了我认为与文件相关的代码。
让我感到困惑的是:为什么 operation(operand) 会计算 UnaryOperation 的值(即平方根)?我看到当 CalculatorBrain class 被调用时,字典被初始化,但是当我打印字典时,我只得到如下内容:[✕: ✕, -: -, +: +, ????: ???? ,√:√]。那么 where/when 当我点击平方根按钮时程序会计算平方根吗?
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("⌹") { / [=12=] })
learnOp(Op.BinaryOperation("+", +))
learnOp(Op.BinaryOperation("-") { [=12=] - })
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()
}
}
learnOp(Op.UnaryOperation ("√", sqrt))
sqrt 是一个内置函数,因此您是在教计算器“√”表示它应该执行 sqrt 运算。
Op
枚举实现了 Printable
协议,这意味着它有一个 description: String
属性。当您打印 Dictionary
时,您将 [String : Op]
发送到 println
函数,该函数然后尝试使用其 description
.
打印 Op
运算符的描述与Dictionary
中的键相同的原因是因为learnOp(op: Op)
函数将键设置为op.description
(knownOps[op.description] = op
)
要查看其效果,您可以添加一个新运算符 learnOp(Op.UnaryOperation ("@", sqrt))
,它将在 knownOps
词典中打印为 @:@
。 (而且如果你为 @
运算符添加一个新按钮,它也会执行平方根运算)
由于计算器是基于堆栈的,因此操作数被推入,然后是操作。当 evaluate()
被调用时,它调用 evaluate(opStack)
传递整个堆栈。
evaluate(ops: [Op])
然后从堆栈中取出 to 项并在 计算完操作数后计算函数 。
例如,假设您要计算 sqrt(4 + 5)。
您将把项目压入堆栈,它看起来像:[ 4, 5, +, sqrt ]
然后 evaluate(ops: [Op])
看到 sqrt
并通过递归调用计算操作数。然后,该调用使用 return 5
和 4
.
两个递归调用评估 +
呼叫树看起来像这样:
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?
函数上放置一个断点,然后单步执行程序以查看不同操作数和操作的执行情况。
我目前正在努力完成 iTunes U 上的 Swift 课程,我们正在构建一个计算器。我无法理解部分代码。
我在下面添加了我认为与文件相关的代码。
让我感到困惑的是:为什么 operation(operand) 会计算 UnaryOperation 的值(即平方根)?我看到当 CalculatorBrain class 被调用时,字典被初始化,但是当我打印字典时,我只得到如下内容:[✕: ✕, -: -, +: +, ????: ???? ,√:√]。那么 where/when 当我点击平方根按钮时程序会计算平方根吗?
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("⌹") { / [=12=] })
learnOp(Op.BinaryOperation("+", +))
learnOp(Op.BinaryOperation("-") { [=12=] - })
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()
}
}
learnOp(Op.UnaryOperation ("√", sqrt))
sqrt 是一个内置函数,因此您是在教计算器“√”表示它应该执行 sqrt 运算。
Op
枚举实现了 Printable
协议,这意味着它有一个 description: String
属性。当您打印 Dictionary
时,您将 [String : Op]
发送到 println
函数,该函数然后尝试使用其 description
.
Op
运算符的描述与Dictionary
中的键相同的原因是因为learnOp(op: Op)
函数将键设置为op.description
(knownOps[op.description] = op
)
要查看其效果,您可以添加一个新运算符 learnOp(Op.UnaryOperation ("@", sqrt))
,它将在 knownOps
词典中打印为 @:@
。 (而且如果你为 @
运算符添加一个新按钮,它也会执行平方根运算)
由于计算器是基于堆栈的,因此操作数被推入,然后是操作。当 evaluate()
被调用时,它调用 evaluate(opStack)
传递整个堆栈。
evaluate(ops: [Op])
然后从堆栈中取出 to 项并在 计算完操作数后计算函数 。
例如,假设您要计算 sqrt(4 + 5)。
您将把项目压入堆栈,它看起来像:[ 4, 5, +, sqrt ]
然后 evaluate(ops: [Op])
看到 sqrt
并通过递归调用计算操作数。然后,该调用使用 return 5
和 4
.
+
呼叫树看起来像这样:
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?
函数上放置一个断点,然后单步执行程序以查看不同操作数和操作的执行情况。