Return statement skipped in Swift

时间:2015-07-28 22:27:02

标签: ios swift return return-value downcast

I'm trying to teach myself Swift via the Stanford iTunes U course (currently working on the calculator app), but I just ran into a super weird issue that I've never seen before and can't figure out how to solve: one of my return statements (and only the return statement itself) is being skipped during runtime.

func evaluateOps(ops: [Op]) -> (result: Double?, remainingOps: [Op]) {

    if !ops.isEmpty {
        var remainingOps = ops
        let op = remainingOps.removeLast()

        switch op {
        case ...
        case ...
        case .BinaryOperation(_, let operation):

            // check that there are 2 operands before it
            if remainingOps.count == 2 {
                let op1Evaluation = evaluateOps(remainingOps)
                if let operand1 = op1Evaluation.result {
                    let op2Evaluation = evaluateOps(op1Evaluation.remainingOps)
                    if let operand2 = op2Evaluation.result {

                        // PROBLEM AREA...
                        let x = (operation(operand1, operand2), op2Evaluation.remainingOps)
                        println("results: \(x.0) remainder: \(x.1)")
                        return (x.0, x.1) // skipped during runtime...
                    }
                }
            }

            else { ... }

        }
    }
    println("returning nil")
    return (nil, ops)
}

// troublesome method is called here...
let (result, remainder) = evaluateOps(opStack)
println("\(opStrings) = \(result) with \(remainderStrings) leftover")

Everything works so that, if I tried to calculate 5*3 for example, the console would read:

results: 15.0 remainder: []
returning nil
[5.0, ×, 3.0] = nil with [5.0, ×, 3.0] leftover

I think the problem might have something to do with the fact that, in the above code, if I tried to simply return x, I get a compile error that reads Cannot express tuple conversion '(Double, [CalculatorModel.Op])' to '(result: Double?, remainingOps: [CalculatorModel.Op])'. I also have no idea what to do with this.

In my researching the problem, I've discovered the downcasting keyword as (see altered code below), which removed the compile error when returning x rather than (x.0, x.1) but results in the same console result (except that now it says results: Optional(15.0) remainder: []):

let x = (operation(operand1, operand2) as Double?, op2Evaluation.remainingOps as [Op])
println("results: \(x.0) remainder: \(x.1)")
return x // no error but same result as return (x.0, x.1)

I've also tried sticking a println(getClassName(x.0!)) just before the return statement to make sure I even had a double, and it spit out __NSCFNumber... which I also researched, and found to be highly underdocumented (or at least not documented well enough to figure out how that's affecting me or how I can fix it!)

Although as you can see, it should be a double...

enum Op {
    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)"
            }
        }
    }
}

As you can see, everything's working perfectly fine as it's performing the calculation and everything...until it gets to that little troublesome area. I've searched StackOverflow and did a bit of Googling, but this seems to be a rather uncommon problem... Any help is appreciated! Let me know if you need any further information. Thanks!

EDIT:

getClassName(_:) is defined below (found it online somewhere...):

func getClassName(obj : AnyObject) -> String
{
    let objectClass : AnyClass! = object_getClass(obj)
    let className = objectClass.description()

    return className
}

0 个答案:

没有答案