//
// CalculatorBrain.swift
// Calculator
//
// Created by 王卓 on 15/6/10.
// Copyright (c) 2015年 王卓. All rights reserved.
//
import Foundation
class CalculatorBrain {
private enum Op:CustomStringConvertible
{
case Operand(Double)
case UnaryOperation(String,Double->Double)
case BinaryOperation(String,(Double,Double)->Double)
var description:String{
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 knowsOps=[String:Op]()
init() {
func learnOp(op:Op){
knowsOps[op.description]=op
}
// ***重点***
// ***闭包***
// switch operation {
// //1最复杂的形式
// case "×":performOperation2({(Double op1,Double op2)->Double in return op1*op2})
// //2
// case "÷":performOperation2({(Double op1,Double op2)->Double in op2/op1})
// //3
// case "+":performOperation2({(op1,op2)->Double in op1+op2})
// //4
// case "−":performOperation2({$1-$0})
// //其他形式performoperation(){$1-$0}
// case "√":performOperation1(){sqrt($0)}
// default:break
// }
//将操作符传入
knowsOps["×"]=Op.BinaryOperation("×", *)
knowsOps["÷"]=Op.BinaryOperation("÷", {$1/$0})
learnOp(Op.BinaryOperation("+", +));
//knowsOps["+"]=Op.BinaryOperation("+", +)
knowsOps["−"]=Op.BinaryOperation("−", {$1-$0})
//将sqrt函数作为参传入
knowsOps["√"]=Op.UnaryOperation("√", sqrt)
}
private func evalucate(ops:[Op])->(result:Double?,remainOps:[Op]){
if !ops.isEmpty{
var remainOps=ops
let op=remainOps.removeLast()
switch op{
case .Operand(let operand):
return (operand,remainOps)
case .UnaryOperation(_, let operation):
let OperandEvalucate = evalucate(remainOps)
if let operand=OperandEvalucate.result{
return (operation(operand),OperandEvalucate.remainOps)
}
case .BinaryOperation(_, let operation):
let op1Evalucate = evalucate(remainOps)
if let operand1=op1Evalucate.result{
let op2Evalucate = evalucate(op1Evalucate.remainOps)
if let operand2=op2Evalucate.result{
return(operation(operand1,operand2),op2Evalucate.remainOps)
}
}
}
}
return(nil,ops)
}
func evalucate()->Double?{
let (result,remainder)=evalucate(opStack)
print("\(opStack) = \(result) with \(remainder) left over")
return result
}
func pushOperand(operand:Double)->Double?{
opStack.append(Op.Operand(operand))
return evalucate()
}
func performOperation(Operation:String)->Double?{
if let operation = knowsOps[Operation]{
opStack.append(operation)
}
return evalucate()
}
}