为什么让x作为Float案例在Any变量的开关中不匹配?

时间:2016-11-30 07:30:20

标签: swift swift3

我有一个标记值的枚举(这是来自玩具Scheme解释器项目),如下所示:

enum Value {
  case int(Int)
  case float(Float)
  case bool(Bool)
  ...
}

我为它写了一个初始化器:

init?(value:Any) {
  switch v {
    case let v as Int: self = .int(v)
    case let v as Float: self = .float(v)
    case let v as Bool: self = .bool(v)
    ...
    default: return nil
  }
}

这样,调用Value(3)会返回(可选)Value.int(3),如预期的那样。布尔和其他类型也有效。

但是Value(0.1)会遇到默认情况并返回nil

(编辑正确性和推荐的风格。感谢大家指出这些问题。)

3 个答案:

答案 0 :(得分:12)

浮点常量的默认推断类型为Double,而不是Float。它由swift标准库定义:https://developer.apple.com/reference/swift/floatliteraltype使用编译器已知的FloatLiteralType typealias。

答案 1 :(得分:5)

type inference的文档说:

  

Swift总是在推断时选择Double(而不是Float)   浮点数的类型。

如果您想使用Float,则必须显式转换文字:

enum Value {
    case Int(Int)
    case Float(Float)
    case Bool(Bool)
    case Double(Double)
    init?(v:Any) {
        switch v {
        case let v as Int: self = .Int(v)
        case let v as Float: self = .Float(v)
        case let v as Bool: self = .Bool(v)
        case let v as Double: self = .Double(v)
        default: return nil
        }
    }
}


Value(v: 0.1) //Infer Double > Result: Double(0.10000000000000001)
Value(v: Float(0.0002)) //Specify Float > Result: Float(0.000199999995)

答案 2 :(得分:1)

顺便说一句,您似乎希望能够使用文字初始化Value类型,因此您可以尝试将您的类型与ExpressibleBy*协议一致。

像:

extension Value: ExpressibleByIntegerLiteral {
    init(integerLiteral value: Int) {
        self = .int(value)
    }
}

let v1: Value = 42 // v1 == Value.int(42)   

extension Value: ExpressibleByBooleanLiteral {
    init(booleanLiteral value: Bool) {
        self = .bool(value)
    }
}

let v2: Value = true // v2 == Value.bool(true)

extension Value: ExpressibleByFloatLiteral {
    init(floatLiteral value: Float) {
        self = .float(value)
    }
}

let v3: Value = 0.5 // v3 == Value.float(0.5)