计数器作为for-in-loops中的变量

时间:2015-01-31 11:33:04

标签: variables swift constants declaration for-in-loop

当正常使用for-in-loop时,计数器(在本例中为number)在每次迭代中都是常量:

for number in 1...10 {
    // do something
}

这意味着我无法在循环中更改number

for number in 1...10 {
    if number == 5 {
        ++number
    }
}

// doesn't compile, since the prefix operator '++' can't be performed on the constant 'number'

有没有办法将number声明为变量,而不是在循环之前声明它,或使用正常的for循环(带初始化,条件和增量)?

2 个答案:

答案 0 :(得分:14)

要理解为什么i不可变,需要知道for…in是什么简写。编译器将for i in 0..<10扩展为以下内容:

var g = (0..<10).generate()
while let i = g.next() {
    // use i
}

每次循环时,i都是一个新声明的变量,即在生成器上调用next来展开下一个结果的值。

现在,while 可以写成:

while var i = g.next() {
    // here you _can_ increment i:
    if i == 5 { ++i }
}

但当然,它无济于事 - g.next()下周仍然会在循环中产生5。身体的增量毫无意义。

大概是因为这个原因,for…in不支持使用相同的var语法来声明它的循环计数器 - 如果你没有意识到它是如何工作的话会非常混乱。

(与where不同,您可以看到正在发生的事情 - var功能偶尔会有用,与func f(var i)的功能类似。

如果您想要跳过循环的某些迭代,那么更好的选择(不使用C风格forwhile)是使用跳过相关值的生成器:< / p>

// iterate over every other integer
for i in 0.stride(to: 10, by: 2) { print(i) }

// skip a specific number
for i in (0..<10).filter({ $0 != 5 }) { print(i) }

let a = ["one","two","three","four"]

// ok so this one’s a bit convoluted...
let everyOther = a.enumerate().filter { $0.0 % 2 == 0 }.map { $0.1 }.lazy

for s in everyOther {
    print(s)
}

答案 1 :(得分:2)

答案是“不”,这是件好事。否则,这样一个非常令人困惑的行为是可能的:

for number in 1...10 {
    if number == 5 {
        // This does not work
        number = 5000
    }
    println(number)
}

想象一下,在一个循环的输出中查看数字5000的人的混淆,该循环被认为绑定到1到10(包括1和10)的范围。

此外,Swift选择下一个5000的值是什么?应该停止吗?是否应继续分配前的范围内的下一个数字?它应该在超出范围的分配上抛出异常吗?这三种选择对他们都有一定的效果,因此没有明显的赢家。

为了避免这种情况,Swift设计者在范围循环中使循环变量不可变。