发布版本中的XCode 6.3 / Swift 1.2 curried函数运行时错误?

时间:2015-04-20 21:21:15

标签: function swift generics currying

这个小通用函数会产生一个有趣的运行时错误:

func clamps <T: Comparable> (from: T, to: T)(_ x: T) -> T {
    if x < from { return from }
    if x > to { return to }
    return x
}

(正如我在下面解释的那样,请记住,我无法进一步显着减少错误生成代码 - 除非删除其中一条if行!)

我们可以使用它来生成clamp函数,如下所示:

let clamp: Int -> Int = clamps(2, 4)

我们会打印一些这样的例子:

for i in 0...5 {
    println("clamp(\(i)) -> \(clamp(i))")
}

在Debug中运行时,for循环产生以下输出:

// clamp(0) -> 2
// clamp(1) -> 2
// clamp(2) -> 2
// clamp(3) -> 3
// clamp(4) -> 4
// clamp(5) -> 4

这是我们所期望的。但是,在Release配置中运行时,我们得到:

// clamp(0) -> 4296676200
// clamp(1) -> 4296676200
// clamp(2) -> 4296676200
// clamp(3) -> 4296676200
// clamp(4) -> 4296676200
// clamp(5) -> 4296676200

请注意,这个数字非常接近UInt32.max(即4294967295),所以我的猜测是它是某种UnicodeScalar值...如果你将clamps与其他类型一起使用,与CGFloat一样,结果也同样荒谬。

如果我们重写函数以避免Swift的currying语法,那么Debug和Release中的一切都可以正常工作:

func clamps2 <T: Comparable> (from: T, to: T) -> T -> T {
    return {
        if $0 < from { return from }
        if $0 > to { return to }
        return $0
    }
}

let clamp2: Int -> Int = clamps2(2, 4)

for i in 0...5 {
    println("clamp2(\(i)) -> \(clamp2(i))")
}

// clamp2(0) -> 2
// clamp2(1) -> 2
// clamp2(2) -> 2
// clamp2(3) -> 3
// clamp2(4) -> 4
// clamp2(5) -> 4

所以问题是这是真的是一个错误,还是我错过了对整个世界显而易见的事情?

作为最后一个例子,考虑这个(一个无用的函数)不会重现错误:

func f <T: Comparable> (from: T, to: T)(_ x: T) -> T {
    if x < from {
        return x // <---- returning x
    }
    return x
}

但这样做:

func f <T: Comparable> (from: T, to: T)(_ x: T) -> T {
    if x < from {
        return from // <---- returning from
    }
    return x
}

Apple Developer Relations回复

我的错误报告刚收到Apple Developer Relations发来的消息称他们认为此问题已在最新的Xcode 7测试版中得到解决。

0 个答案:

没有答案