Swift使方法参数可变吗?


123

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

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

我不想创建其他变量只是为了存储x的值。有可能做我想做的事吗?


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

Answers:


191

如其他答案所述,从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'

这在递归中特别有用。

苹果的inout声明指南可以在这里找到。


2
非常感谢你!!!!我被困在递归问题上。你救了我的命。
JW.ZG,2016年

2
请谨慎使用,因为这会修改函数范围之外的变量。理想情况下,您要显式返回在函数内部更改的值。
克里斯·古纳瓦德纳

2
inout关键字应放在参数名称和参数类型之间,如下所示:func reduceToZero(x: inout Int) 在当前的Swift 3版本中。
奥古斯特·桑切斯

除此之外,这似乎不适用于闭包,因为闭包显然只能按值捕获inout参数(至少这是Xcode给我的错误消息)。在这种情况下,我使用@GeRyCh解决方案。
wcochran

谢谢。它现在可以使用,但是就像在C语言中使用指针一样。这样可以在另一个Swift版本中生存吗?
克里希纳·维杜拉'17

45

'var'参数已被弃用,并将在Swift 3中删除。因此,分配新参数似乎是最好的方法:

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

如此处所述:'var'参数已弃用,并将在Swift 3中删除


1
在这种情况下,它实际上是否将拷贝x到新的var x吗?还是Swift可以做得比这更有效?
Genki

3
这是可行的,而且是我的工作,但似乎很尴尬。
wcochran

1
@Gomfucius在Swift 3.1指南中对此一言不发。在这种情况下(x适合套准),几乎没有成本。如果x是被突变的数组,结构或对象,则几乎肯定需要执行一个副本(除非优化器可以对其进行内联分析并对其进行别名)。
wcochran

1
@wcochran这是一个巧妙的技巧,但实际上并没有什么特别的事情。它只是用本地var副本遮盖了输入参数。在OP的情况下,用varargs 替代使用args inout可能会产生意想不到的副作用,尤其是。如果var是一个指针。
梯队

45

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

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

2
为什么这个答案像地狱一样被投票?另一个答案位于该答案之前,并且包含的​​信息比该答案更多。
Cristik

16
/!\使用var将创建传入参数的变量的副本。因此,修改它不会修改原始值。同样var在参数中很有可能会在github.com/apple/swift-evolution/blob/master/proposals/…的
Matthieu Riegler

17
在方法paremeter var关键字将在斯威夫特3.被弃用
皇家

4
我认为使用Swift 3,我们将无法再执行此操作。我们将不得不创建数组的变量副本并返回修改后的数组。
C0D3 '16

这个答案是正确的答案:stackoverflow.com/questions/24077880/...
ACHI

14

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

功能:

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

调用函数:

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

老实说,由于Swift领域的变化,我不确定这是否正确。我认为这比在函数内部执行var array = array更好,因为它可以进行复制(并且实际上不影响原始数组结构)?是一种比上述var方法更好的设计方法,然后返回新的变异数组吗?
2013年

7

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

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

请参阅Swift书(今天,iBook的第210页)的“函数”一章中的“常量和变量参数”小节。


7
'var'参数已弃用,并将在Swift 3中删除
Regis St-Gelais,2016年

1
对Swift 4及更高版本无效。
ilkayaktas

0

在某些情况下,我们不愿使用 inout

如果您希望更改/作用域仅在函数内部,我们可以使用如下所示的方法:

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

0

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

func reduceToZeroFP(x:Int) -> Int {
    x == 0 ? x : reduceToZeroFP(x: x - 1)
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.