【问题标题】:Swift - Enum Returning The Wrong Value TypeSwift - 枚举返回错误的值类型
【发布时间】:2015-10-04 19:12:43
【问题描述】:

我遇到以下代码问题:

private enum Op : Printable {
    case Operand(Double)
    case Constant(String, Double)
    case Variable(String)
    case UnaryOperation(String, Double -> Double)
    case BinaryOperation(String, (Double, Double) -> Double)
    var description: String {
        get {
            switch self {
            case .Operand(let operand):
                return "\(operand)"
            case .Constant(let constant, _):
                return constant
            case .Variable(let variable):
                return variable
            case .UnaryOperation(let symbol, _):
                return symbol
            case .BinaryOperation(let symbol, _):
                return symbol
            }
        }
    }
}

private var knownOps = [String:Op]()

init() {
    func learnOp(op: Op) {
        knownOps[op.description] = op
    }
    learnOp(Op.Constant("π", M_PI))
    learnOp(Op.UnaryOperation("√", sqrt))
    learnOp(Op.UnaryOperation("sin", sin))
    learnOp(Op.UnaryOperation("cos", cos))
    learnOp(Op.UnaryOperation("±") { -1 * $0 })
    learnOp(Op.BinaryOperation("×", *))
    learnOp(Op.BinaryOperation("÷") { $1 / $0 })
    learnOp(Op.BinaryOperation("+", +))
    learnOp(Op.BinaryOperation("-") { $1 - $0 })
}

init() 完成后,字典knownOps 包含以下内容:

knownOps    [String : Calculator.CalculatorModel.Op]    9 key/value pairs   
[0] _DictionaryElement<String, Calculator.CalculatorModel.Op>       
key String  "×" 
value   Calculator.CalculatorModel.Op   Operand Operand
[1] _DictionaryElement<String, Calculator.CalculatorModel.Op>       
key String  "+" 
value   Calculator.CalculatorModel.Op   Operand Operand
[2] _DictionaryElement<String, Calculator.CalculatorModel.Op>       
key String  "÷" 
value   Calculator.CalculatorModel.Op   Operand Operand
[3] _DictionaryElement<String, Calculator.CalculatorModel.Op>       
key String  "π" 
value   Calculator.CalculatorModel.Op   Constant    Constant
[4] _DictionaryElement<String, Calculator.CalculatorModel.Op>       
key String  "-" 
value   Calculator.CalculatorModel.Op   Operand Operand
[5] _DictionaryElement<String, Calculator.CalculatorModel.Op>       
key String  "±" 
value   Calculator.CalculatorModel.Op   UnaryOperation  UnaryOperation
[6] _DictionaryElement<String, Calculator.CalculatorModel.Op>       
key String  "sin"   
value   Calculator.CalculatorModel.Op   UnaryOperation  UnaryOperation
[7] _DictionaryElement<String, Calculator.CalculatorModel.Op>       
key String  "√" 
value   Calculator.CalculatorModel.Op   UnaryOperation  UnaryOperation
[8] _DictionaryElement<String, Calculator.CalculatorModel.Op>       
key String  "cos"   
value   Calculator.CalculatorModel.Op   UnaryOperation  UnaryOperation

我的问题是:为什么binaryOperations 在字典中被捕获为Operands?

【问题讨论】:

  • 如何查看knownOps的内容?通过调试器?还是打印出来?
  • 我通过 Xcode 中的调试器检查了它。

标签: swift dictionary enums key


【解决方案1】:

我在您的枚举中添加了以下变量:

var type: String {
    get {
        switch self {
        case .Operand:
            return "Operand"
        case .Constant:
            return "Constant"
        case .Variable:
            return "Variable"
        case .UnaryOperation:
            return "UnaryOperation"
        case .BinaryOperation:
            return "BinaryOperation"
        }
    }
}

然后使用以下代码循环遍历字典:

for (key, value) in knownOps
{
    let valueType = value.type
    println("\(key) : \(valueType)")
}

这给了我输出:

× : BinaryOperation
+ : BinaryOperation
÷ : BinaryOperation
π : Constant
- : BinaryOperation
± : UniaryOperation
sin : UniaryOperation
√ : UniaryOperation
cos : UniaryOperation

所以我猜你的问题的答案是它不是。我无法回答为什么调试器或您用来检查值的任何内容不正确,但您发布的代码并没有错。

【讨论】:

  • 我实现了相同的代码并收到了相同的结果。谢谢!
【解决方案2】:

好的,我想我设法重现了您在问题中所说的话。如果我在 Xcode 6.4 中以调试模式运行该东西,放置一个断点并检查 knownOps 的内容,那么我确实看到二进制操作仅存储为一个操作数。

我认为正在发生的是 Swift 编译器优化加上一个错误。

我认为是这样的原因是:

  • 与 Xcode 7 beta 类似的代码(刚刚移植)将 enum 中的 knownOps 呈现为 Invalid
  • 如果我通过打印出 knownOps 的内容(例如在 for 循环中)来“检查”它们,那么无论在 Xcode 6.4 还是在 Xcode 7 beta 中,所有内容都会按预期打印出来。
  • 如果我通过单步执行指令来跟踪打印出knownOps 内容的代码的执行,那么我看不到任何类似的内容:1) 检查enum 属性存储的值,然后检查 2 ) 基于属性的值,决定返回什么作为enum 的计算属性description

因此,您的代码很可能足够简单,编译器能够“预测”必须打印出的内容或执行路径的外观,从而将所有“不必要的”内容都扔掉。而且可能 6.4 中的调试器根本跟不上这件事的速度..

但好消息是来自 Xcode 7 的调试器“知道”这一点。它说invalid,而不是用虚假的东西喂你。

【讨论】:

  • 优秀的答案。你的推理使我不再关注这个错误,而是在软件的其他部分找到了错误(尽管它很小!)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-23
  • 1970-01-01
  • 1970-01-01
  • 2018-05-02
相关资源
最近更新 更多