Swift 中无法理解的错误

Incomprehensible errors in Swift

这个有效:

func averageOf(numbers: Int...) -> Float {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return Float(sum) / Float(numbers.count)
}
averageOf() // (not a number)
averageOf(42, 597, 12) // (217.0)

但事实并非如此:

func averageOf(numbers: Int...) -> Float {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return Float(sum / numbers.count)
}
averageOf()
averageOf(42, 597, 12)

它在 } 行给我这个错误:

Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

我偶然发现 another question 具有相同的第一段和第二段代码,而作者显然没有得到相同的错误。

让我们删除该演员表:

func averageOf(numbers: Int...) -> Float {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum / numbers.count
}
averageOf()
averageOf(42, 597, 12)

它给了我这个错误,在除号上:

Cannot invoke '/' with an argument list of type '(@lvalue Int, Int)'

如果我然后将函数的 return 类型更改为 Int:

func averageOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum / numbers.count
}
averageOf()
averageOf(42, 597, 12)

我得到了同样的 EXC_BAD_INSTRUCTION 错误。

如果我只投numbers.count:

func averageOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum / Float(numbers.count)
}
averageOf()
averageOf(42, 597, 12)

我在除号上遇到这个错误:

Cannot invoke 'init' with an argument list of type '(@lvalue Int, $T5)'

如果我将 return 类型改回 Float,我也会收到此错误。

所有这些对我来说毫无意义。是 Xcode 邮寄,还是我漏掉了一些微妙的东西?

发生此错误是因为您的函数调用 averageOf()
如果您未传递任何值,可变参数 numbers 将创建一个空数组。
它是 count 属性 因此 returns 0。而且你不能除以 0。 这也是为什么它说 BAD_INSTRUCTION.

的原因

如果您从第二个代码示例中删除 averageOf(),它会起作用。

如前所述,第二个示例中的问题是由于不带参数调用 averageOf(),导致被零除。但是,第一个 averageOf() 仍然没有参数,为什么?让我再补充一些细节。

在您报告的第一种情况下,您没有收到任何错误并且 averageOf() 有效,因为您在除法之前将两个 Int 操作数转换为 Float
Float 数字的世界中,0.0 只是 0 的近似值。如果你在 Playground 中尝试 0.0 / 0.0,你不会因此得到错误,相反,输出将是 not a number.

然而,在第二种情况下,您试图在转换为 Float 之前将 0 除以 0。所以,我们在进行除法的时候,还是在Int个数的境界。由于除以零(此处不涉及近似值),结果是错误的。如果你在 Playground 中尝试 0 / 0,你会得到一个错误。

IntFloat 行为无法解释的所有其他情况,是由于 Swift 要求您在类型之间显式转换,即使另一种语言会让您隐式转换操作数。