Swift switch 语句的范围错误

Swift range bug with switch-statement

大家好,我是新来的,现在我正在通过编写一些奇特的算法来学习 Swift,这是我在阅读 Apples Swift 书时想到的。

我试图压缩(自动向下转换)任何 IntegerType 值。 这是我的代码的一小段,除了一种情况外几乎可以正常工作:

switch signedValue
{
case Int64(Int8.min)...Int64(Int8.max):          compressedValue = Int8(signedValue)
case (Int64(Int8.max) + 1)...Int64(UInt8.max):   compressedValue = UInt8(signedValue)
case Int64(Int16.min)...Int64(Int16.max):        compressedValue = Int16(signedValue)
case (Int64(Int16.max) + 1)...Int64(UInt16.max): compressedValue = UInt16(signedValue)
case Int64(Int32.min)...Int64(Int32.max):        compressedValue = Int32(signedValue)
case (Int64(Int32.max) + 1)...Int64(UInt32.max): compressedValue = UInt32(signedValue)
case Int64(Int.min)...Int64(Int.max):            compressedValue = Int(signedValue) // range bug #1 - workaround '..<'
default:                                         compressedValue = signedValue
}

假设 signedValue 的类型为 Int64,输入值为 = 10_000_000_000。 这将导致运行时错误(在 Playground 中):

Execution was interrupted, reason: EXC_BAD_INSTRUCTION ...

任何人都可以帮助我了解这里到底发生了什么。此问题有一个解决方法。我可以使用 '..<' 而不是 '...' 但这不是范围应该如何。

与间隔(有两种风格,半开或封闭)不同,Range 只是半开。因此,当您编写 1...5 时,... 函数会递增右侧参数以创建半开范围 1..<6.

这样做的结果是您不能拥有跨越整数类型整个长度的范围,因为 1...Int.max 将导致尝试递增 Int.max,并出现溢出错误. let s = "hello"; let r = s.startIndex...s.endIndex

会出现类似的错误

然而,一切都没有丢失,因为无论如何你都不应该使用范围,这是 ClosedInterval 的工作。由于 ... 运算符用于两者,并且默认为范围(出于重载优先级原因),您需要明确标识类型:

let i64interval: ClosedInterval = Int64(Int64.min)...Int64(Int64.max)
switch signedValue {
    // etc
    case i64interval:   compressedValue = Int(signedValue)
    default:            compressedValue = signedValue
}

the documentation 中查看 Range 类型。它包含以下我以前从未注意到的小信息:

if T has a maximal value, it can serve as an endIndex, but can never be contained in a Range.

T,在那个引用中,是 Range 中值的类型。因此,如果您有 IntRange,则 Int 的最大值不能包含在 Range.

这就是为什么如果你把 ..< 放在那里,而不是 ...

好问题,顺便说一句...