Programming in Swift – perhaps badly

I have been periodically dabbling in learning Apple’s relatively new Swift programming language. Despite many years of experience in a number of languages including C, C++, C# and Objective-C – yep, that’s a lot of C’s! – my primary reasons for wanting to learn Swift is mental exercise and general interest. My day job these days involves very little programming, but I still consider myself a software developer at heart despite moving heavily into the management side of things. So it is good to keep current and familiar with later technologies. And a further reason for choosing Swift is my interest in developing mobile applications, and Swift looks to be the future of iOS development.

My primary source for learning has been the excellent free Stanford University course CS193P: Developing iOS Apps with Swift, presented by the hugely engaging Paul Hegarty. This course is available for free via iTunesU as a series of videos, slides, and practical exercises. I cannot recommend it enough.

This article is about the homework task of extending the Calculator demo: specifically adding a recursive description method to the CalculatorBrain object to present a readable and mathematically correct text description of the contents of the calculator’s operation stack.

The code snippet below is my implementation. The public getter for the description property contains a loop to solve the formatted output of multiple separate expressions, each comma separated, and is pretty straightforward:

 

    var description: String {
        get {
            var descriptionText = ""
            var (desc,remainingOps) = formatDescription(opStack)
            descriptionText = desc!
            while remainingOps.count > 0 {
                // Comma separate any following complete expressions
                let (desc1,remainingOps1) = formatDescription(remainingOps)
                if desc1 != nil {
                    descriptionText = desc1! + "," + descriptionText
                }
                remainingOps = remainingOps1
            }
            return descriptionText
        }
    }
    

The guts of the solution is in the recursive formatDescription method. It works for the test cases mentioned in the assignment, for example, an operation stack entered in this order:

3 <enter> 5 <enter> 4 + +

gets displayed as:

3+(5+4)

It also handles error conditions such as missing operands being displayed as “?”. So it works.

 
    // Recursive function to format description string
    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 op1ActualText = op1Text ?? "?"
                let returnText = "\(operation)(\(op1ActualText))"
                return (returnText, remainingOps1)
            case .BinaryOperation(let operation,_):
                let (op1Text, remainingOps1) = formatDescription(remainingOps)
                let (op2Text, remainingOps2) = formatDescription(remainingOps1)
                let op1TextActual = op1Text ?? "?"
                let op2TextActual = op2Text ?? "?"
                let returnText = "\(op2TextActual) \(operation) \(op1TextActual)"
                return (returnText, remainingOps2)
            case .Variable(let variable):
                return (variable, remainingOps)
            case .Constant(let constant):
                return (constant, remainingOps)
            }
        }
        return (nil, ops)
    }

This brings me to the point of this blog post – I think I’m missing something. The formatDescription method does not feel very elegant. Swift has a fantastic type inference engine, and features like optional chaining, which I feel my solution does not take advantage of. You could say it is a little too C or C++ like. All those “let” statements seem overkill.

What do you think? Is there a better more elegant solution?

Leave a Reply