调用从闭包中使用inout数组的函数

时间:2014-09-10 04:03:24

标签: swift

我决定更新我在Swift beta 1期间制作的项目,现在Swift 1.0已经用完了。但是,由于更新的数组语义和inout关键字,我似乎无法解决这个问题。考虑以下两个功能(您可以将它们粘贴到游乐场中):

func bubbleSort<T : Comparable>(inout arr : [T]) {
    var numSwaps = 0
    do {
        numSwaps = 0
        for i in 0..<(arr.count - 1) {
            if arr[i] > arr[i + 1] {
                (arr[i], arr[i + 1]) = (arr[i + 1], arr[i])
                numSwaps++
            }
        }
    } while numSwaps != 0
}

func testFunc(sortFunc: ([Int]) -> ()) {
    sortFunc([5,4,3,2,1])
}

我似乎无法让两者协同工作。我尝试使用速记:

testFunc {bubbleSort(&$0)}

我也试过没有速记:

testFunc { (arr: [Int]) -> () in
    bubbleSort(&arr)
}

在任何一种情况下,我都会收到错误:

error screenshot

这是一个错误,还是我搞砸了什么?提前谢谢!

2 个答案:

答案 0 :(得分:3)

您遇到的是默认情况下方法参数是不可变的,而输入输出函数是变异的。你不能使用闭包速记,因为你需要使用var关键字将闭包的参数声明为可变的,如下所示:

func testFunc(sortFunc: ([Int]) -> ()) {
    sortFunc([5,4,3,2,1])
}

testFunc { (var arr: [Int]) -> () in
    bubbleSort(&arr)
}

现在,您可以使用bubbleSort作为输入输出参数调用arr

答案 1 :(得分:2)

您遇到的是beta 3的变化(如果我没记错的话),更改数组的en元素变为mutating操作。在此之前,更改元素是非变异操作,因此您可以更改Array常量上的元素;你无法改变它的长度。但是从beta 3开始,要更改数组中的元素,它必须是非常量的。

bubbleSort通过引用(inout)获取数组,因为它需要更改数组的元素并使其对调用者可见(在beta 3之前,它只是按值获取) 。您只能通过引用传递非常量变量。在您写的闭包中,arr是一个常量(它是一个未声明为varinout的数组参数),因此您无法通过引用传递它。

显而易见的答案是arr必须是varinout。您需要哪一个取决于这些功能的目的。你现在所拥有的是丢弃调用的结果,这是毫无意义的,所以你显然没有告诉我们这些功能应该做什么。

@ NakeCook的回答,只需让arr成为var,就可以通过引用传递它,但它并没有改变闭包采用其参数的事实by value(以及sortFunc中的testFunc是一个按值传递的函数。这意味着testFunc给函数排序一个数组,但不关心或想要更改要反映回来。如果这是你想要的,那就是答案。

但是,如果testFunc应该有一个数组,将它传递给sort函数进行排序,并希望在其范围内看到对数组的更改,那么它需要做其他事情:

func testFunc(sortFunc: (inout [Int]) -> ()) {
  var x = [5,4,3,2,1]
  sortFunc(&x)
}

testFunc { (inout arr: [Int]) -> () in
  bubbleSort(&arr)
}

在这种情况下,闭包的参数被声明为inout(因此它通过引用传递),以及sortFunc(在testFunc中) &#39;类型明确提到它通过引用获取其参数。