当正常使用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循环(带初始化,条件和增量)?
答案 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风格for
或while
)是使用跳过相关值的生成器:< / 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设计者在范围循环中使循环变量不可变。