嵌套函数使Swift编译器崩溃

嵌套函数使Swift编译器崩溃,swift,generics,nested,mergesort,nested-generics,Swift,Generics,Nested,Mergesort,Nested Generics,我编写了一个递归的mergeSort函数: func mergeSort<T: Comparable>(inout array: [T]) { if array.count <= 1 { return } var leftSlice = [T](array[0..<array.count / 2]) var rightSlice = [T](array[array.count / 2...array.endIndex -

我编写了一个递归的
mergeSort
函数:

func mergeSort<T: Comparable>(inout array: [T]) {
    if array.count <= 1 {
        return
    }

    var leftSlice = [T](array[0..<array.count / 2])
    var rightSlice = [T](array[array.count / 2...array.endIndex - 1])

    mergeSort(&leftSlice)
    mergeSort(&rightSlice)
    array = merge(leftSlice, rightSlice)
}

func merge<T: Comparable>(var left: [T], var right: [T]) -> [T] {
    var mergedValues = [T]()

    while !left.isEmpty && !right.isEmpty {
        mergedValues.append(left.first! < right.first! ? left.removeAtIndex(0) : right.removeAtIndex(0))
    }

    if !left.isEmpty {
        mergedValues += left
    } else if !right.isEmpty {
        mergedValues += right
    }

    return mergedValues
}
func merge(var left: [T], var right: [T]) -> [T] {
    var mergedValues = [T]()
    ...
}
现在这个版本可以正常工作,但这个版本不行。

这怎么可能呢?

您不需要将
合并
作为通用函数。通用
T
已为
mergeSort
定义,因此您只需将
[T]
设置为内部函数中的参数:

func mergeSort<T: Comparable>(inout array: [T]) {
    if array.count <= 1 {
        return
    }

    var leftSlice = [T](array[0..<array.count / 2])
    var rightSlice = [T](array[array.count / 2...array.endIndex - 1])

    mergeSort(&leftSlice)
    mergeSort(&rightSlice)
    array = merge(leftSlice, rightSlice)
}

func merge<T: Comparable>(var left: [T], var right: [T]) -> [T] {
    var mergedValues = [T]()

    while !left.isEmpty && !right.isEmpty {
        mergedValues.append(left.first! < right.first! ? left.removeAtIndex(0) : right.removeAtIndex(0))
    }

    if !left.isEmpty {
        mergedValues += left
    } else if !right.isEmpty {
        mergedValues += right
    }

    return mergedValues
}
func merge(var left: [T], var right: [T]) -> [T] {
    var mergedValues = [T]()
    ...
}

看起来您在编译器中发现了与嵌套泛型函数相关的错误。以下是一个也会使1.2编译器崩溃的缩减:

func f<T>(t: T) {
    func g<U>(u: U) { }
}
这似乎效果不错

但是,还值得指出的是,在
merge
函数中,您正在循环中调用
removatendex
,这是一个O(n)函数。这意味着您的合并排序将不会具有所希望的复杂性

以下是另一个需要考虑的版本:

func mergeSort<T: Comparable>(inout array: [T], range: Range<Int>? = nil) {

    func merge(left: Range<Int>, right: Range<Int>) -> [T] {    
        var tmp: [T] = []
        tmp.reserveCapacity(count(left) + count(right))

        var l = left.startIndex, r = right.startIndex

        while l != left.endIndex && r != right.endIndex {
            if array[l] < array[r] {
                tmp.append(array[l++])
            }
            else {
                tmp.append(array[r++])
            }
        }
        // where left or right may be empty, this is a no-op
        tmp += source[l..<left.endIndex]
        tmp += source[r..<right.endIndex]

        return tmp
    }

    // this allows the original caller to omit the range,
    // the default being the full array
    let r = range ?? indices(array)
    if count(r) > 1 {
        let mid = r.startIndex.advancedBy(r.startIndex.distanceTo(r.endIndex)/2)
        let left = r.startIndex..<mid
        let right = mid..<r.endIndex

        mergeSort(&array, range: left)
        mergeSort(&array, range: right)
        let merged = merge(left, right)
        array.replaceRange(r, with: merged)
    }
}
func合并排序(inout数组:[T],范围:范围?=nil){
函数合并(左:范围,右:范围)->[T]{
变量tmp:[T]=[]
tmp.储备容量(计数(左)+计数(右))
变量l=left.startIndex,r=right.startIndex
而l!=left.endIndex&&r!=right.endIndex{
如果数组[l]<数组[r]{
追加(数组[l++])
}
否则{
append(数组[r++])
}
}
//如果left或right可能为空,则表示无操作

tmp+=source[l..我也注意到了这一点。如果我引入嵌套泛型,游乐场甚至不会运行,尝试使用嵌套泛型编译会产生分段错误。是的,这是编译器崩溃而不是运行时错误(我编辑了问题标题)好的,我有几个问题:(1)你怎么知道
removatendex
需要O(n)时间?||(2)在使用
let
定义的数组上使用
reserveCapacity
,是否可以在不初始化的情况下创建静态数组?(3)您为什么对Swift了解这么多?(1)答案很简单:它在文档中:)将鼠标悬停在
removeAtIndex
上,您将看到信息。而且,直观的是,Swift中声明的数组是一个连续的内存块–所有后续元素都需要向下移动以填补空白。事实上,删除第一个元素是最糟糕的情况,因为这意味着maximum shuffling。(2)没有,但想一想为什么这没有意义——
let
声明一个不可变的值,数组是值类型,所以如果用
let
声明,它们永远不能被添加到其中——那么为什么要保留额外的空间?(3)实验!