我有一个标记值的枚举(这是来自玩具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
。
(编辑正确性和推荐的风格。感谢大家指出这些问题。)
答案 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)