【问题标题】:Swift make method parameter mutable?Swift使方法参数可变?
【发布时间】:2014-07-27 11:46:36
【问题描述】:

如何在不创建额外变量的情况下处理此错误?

func reduceToZero(x:Int) -> Int {
    while (x != 0) {
        x = x-1            // ERROR: cannot assign to 'let' value 'x'
    }
    return x
}

我不想创建额外的变量来存储 x 的值。甚至可以做我想做的事吗?

【问题讨论】:

  • 请参阅下面的更新答案,Swift 3 已弃用您接受的答案。

标签: swift syntax immutability mutability


【解决方案1】:

正如其他答案中所述,从 Swift 3 开始,将 var 放在已弃用的变量之前。虽然在其他答案中没有说明是声明inout 参数的能力。思考:传入一个指针。

func reduceToZero(_ x: inout Int) {
    while (x != 0) {
        x = x-1     
    }
}

var a = 3
reduceToZero(&a)
print(a) // will print '0'

这在递归中特别有用。

Apple 的inout 声明指南可在here 找到。

【讨论】:

  • 非常感谢!!!!我被困在一个递归问题上。你救了我的命。
  • 应该谨慎使用它,因为它会修改函数范围之外的变量。理想情况下,您希望显式返回您在函数内更改的值。
  • inout 关键字应放在参数名称和参数类型之间,如下所示:func reduceToZero(x: inout Int) 在当前 Swift 3 版本中。
  • 除了这似乎不适用于闭包,因为闭包显然只按值捕获 inout 参数(至少这是 Xcode 给我的错误消息)。在这种情况下,我使用@GeRyCh 解决方案。
  • 谢谢。这暂时可行,但它就像在 C 中使用指针一样。这会在另一个 Swift 版本中存活吗?
【解决方案2】:

'var' 参数已被弃用,将在 Swift 3 中删除。 所以现在分配给一个新参数似乎是最好的方法:

func reduceToZero(x:Int) -> Int {
    var x = x
    while (x != 0) {
        x = x-1            
    }
    return x
}

这里提到:'var' parameters are deprecated and will be removed in Swift 3

【讨论】:

  • 在这种情况下,它是否真的复制了新的var x 中的x?还是 Swift 做的事情比这更高效?
  • 这行得通,也是我所做的,但看起来很尴尬。
  • @Gomfucius 在 Swift 3.1 指南中只字未提。在这种情况下(x 适合注册)几乎没有成本。如果x 是数组、结构体或发生变异的对象,那么几乎肯定需要执行复制(除非优化器可以内联分析它并为其取别名)。
  • @wcochran 这是一个巧妙的技巧,但实际上并没有什么特别之处。它只是用本地 var 副本使输入参数黯然失色。在 OP 的情况下,它比使用 inout 更好地替代 var 参数,这可能会产生意想不到的副作用,尤其是。如果 var 是一个指针。
  • 那么我们应该使用这种方法还是inout方法呢?
【解决方案3】:

对于 Swift 1 和 2(对于 Swift 3,请参阅 achi 使用 inout 参数的答案):默认情况下,Swift 中函数的参数为​​ let,因此如果需要更改值,请将其更改为 var 即,

func reduceToZero(var x:Int) -> Int {
    while (x != 0) {
        x = x-1     
    }
    return x
}

【讨论】:

  • 为什么这个答案的投票率高得离谱?另一个答案放在这个答案之前,并且包含比这个答案更多的信息。
  • /!\ 使用 var 将创建传入参数的变量的副本。所以修改它不会修改原始值。此外,var 参数中的 github.com/apple/swift-evolution/blob/master/proposals/… 很可能在较新的 Swift 版本中消失@
  • 方法参数中的 var 关键字将在 Swift 3 中被弃用。
  • 我认为使用 Swift 3,我们将无法再这样做了。我们必须创建数组的变量副本并返回修改后的数组。
  • 这个答案是正确答案:stackoverflow.com/questions/24077880/…
【解决方案4】:

Swift3 传递可变数组指针的答案。

功能:

func foo(array: inout Array<Int>) {
    array.append(1)
}

调用函数:

var a = Array<Int>()
foo(array:&a)

【讨论】:

  • 老实说,我不确定这是否正确,因为 Swift 的基础是不断变化的。我认为这比在函数内执行 var array = array 更好,因为这会复制(并且实际上不会影响原始数组结构)?上述 var 方法是否有更好的设计方法,然后返回新的变异数组?
【解决方案5】:

在 Swift 中,您只需在函数声明中的变量名前添加 var 关键字:

func reduceToZero(var x:Int) -> Int { // notice the "var" keyword
    while (x != 0) {
        x = x-1            
    }
    return x
}

请参阅 Swift 书籍 "Functions" chapter 中的“常量和变量参数”小节(iBook 的第 210 页,就像现在一样)。

【讨论】:

  • 'var' 参数已弃用,将在 Swift 3 中删除
  • 不适用于 Swift 4 和更新版本。
【解决方案6】:

在某些情况下我们不需要使用inout

如果您希望更改/范围仅在函数内部,我们可以使用类似的方法:

func manipulateData(a: Int) -> Int {
    var a = a
    // ...
}

【讨论】:

    【解决方案7】:

    使用 Swift5 和函数式编程的解决方案...

    func reduceToZeroFP(x:Int) -> Int {
        x == 0 ? x : reduceToZeroFP(x: x - 1)
    }
    

    【讨论】:

      猜你喜欢
      • 2016-08-11
      • 2016-07-18
      • 1970-01-01
      • 2020-02-14
      • 2014-08-03
      • 1970-01-01
      • 1970-01-01
      • 2016-05-08
      相关资源
      最近更新 更多