In my earlier I post I talked about not being very sure that a method I wrote for one of the Stanford iOS Programming course assignments was really embracing Swift as a language. I then posted about using Swift’s unit test framework that would make any refactoring easier and better.
And so on to the refactoring…
Well, with a fresh day came a fresh eye, and there was not too much I could really do to make the method more Swift than C/C++. I ended up mainly folding some let statements into inline expressions. Not exactly hard, but when all was completed I think the code is more or less as tight as it could be and still easily readable – opinions to the contrary are very welcome.
Here’s the revised method (see one of articles linked to above for the original code):
private func formatDescription(ops: [Op]) -> (desc: String?, 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 (op1Text, remainingOps1) = formatDescription(remainingOps)
let returnText = "\(operation)(\(op1Text ?? "?"))"
return (returnText, remainingOps1)
case .BinaryOperation(let operation,_):
let (op1Text, remainingOps1) = formatDescription(remainingOps)
let (op2Text, remainingOps2) = formatDescription(remainingOps1)
let returnText = "\(op2Text ?? "?") \(operation) \(op1Text ?? "?")"
return (returnText, remainingOps2)
case .Variable(let variable):
return (variable, remainingOps)
case .Constant(let constant):
return (constant, remainingOps)
}
}
return (nil, ops)
}
Because of the unit tests written before, it was trivial to ensure the before and after are functionally equivalent.
I did end up adding a handful of extra unit tests to ensure cases where an operand was missing was correctly handled:
func testDescriptionMissingOperand() {
brain.performOperation("cos")
XCTAssert(brain.description == "cos(?)")
}
func testDescriptionMissingOperand2() {
brain.pushOperand(4)
brain.performOperation("+")
XCTAssert(brain.description == "? + 4.0")
}
Note that the code as presented does not yet implement the whole assignment. The main piece missing is adding the formatting of expressions correctly with brackets by considering operator precedence.