Swift用于输入条目作为参考
有没有一种方法可以为..生成Swift用于输入条目作为参考,swift,for-loop,pass-by-reference,Swift,For Loop,Pass By Reference,有没有一种方法可以为..生成。。在循环中,返回对集合项的引用,而不是副本的引用 假设我有一个由CGPoint对象组成的数组points,我想循环它们,并将每个点传递给一个函数adjustPoint,该函数可以使用inout参数修改该点 现在执行以下操作不起作用,因为。。in循环将点返回为不可变/可变(取决于我是否使用var)复制数组中的实际点: for var point in points { adjustPoint(point: &point) // This functi
。。在
循环中,返回对集合项的引用,而不是副本的引用
假设我有一个由CGPoint
对象组成的数组points
,我想循环它们,并将每个点传递给一个函数adjustPoint
,该函数可以使用inout
参数修改该点
现在执行以下操作不起作用,因为。。in循环将点返回为不可变/可变(取决于我是否使用var
)复制数组中的实际点:
for var point in points {
adjustPoint(point: &point) // This function only changes the copy
}
目前,我看到的唯一方法是循环索引:
for i in 0..<points.count {
adjustPoint(point: &points[i])
}
for i in 0..因此,原始for
循环问题的基本答案是:否。for…in
旨在为您提供值类型的副本。正如您在评论中所说,这是一种强制函数式编程风格
要改变数组,你必须以某种方式说array[index]
,现在你指的是原始值,可以改变它。诀窍在于找到一种能够防止常见错误的表达方式。以下是我提倡的四种技巧:
将一个强大的抽象作为一个扩展
,这样你就可以在整个代码中干涸
使用索引
不是一个也容易出错的手动范围(..
与相比)。也许您可以尝试将它们包装在一个类中。为什么不使用map?您将创建副本,但points=points.map{adjustPoint(point:$0)}
就可以了。是的,我想函数式方法是下一个最好的选择,可以保持事情的整洁,但我仍然不喜欢这样一个事实,即Swift使正确使用引用变得如此烦人,相反,您拥有所有这些“一次性使用”到处都是变量副本。这可能只是个人喜好…@jjatie还有,如果我不想更新最后n个条目以外的所有条目怎么办。有没有一种方法可以使用地图来做到这一点?我认为这里对Swift数组有一个误解。你从来没有真正修改过Swift数组,就像你在修改时修改了数字4一样对数组的每一次修改都会创建一个新的数组(比如将1和4相加会创建一个新的Int)。在某些情况下,编译器可以使新的副本非常便宜(通过证明没有人能看到旧的副本,所以只需在适当的位置对旧的副本进行变异),但从逻辑上讲,而且在很多情况下,赋值后的数组与赋值前的数组是完全不同的数据结构,因此不能引用单个元素。
import Foundation
import CoreGraphics
protocol Pointy {
var x: CGFloat { get set }
var y: CGFloat { get set }
func adjustBy(amount: CGFloat) -> CGPoint
mutating func adjustInPlace(amount: CGFloat) -> Void
}
extension CGPoint: Pointy {
func adjustBy(amount: CGFloat) -> CGPoint {
return CGPoint(x: self.x + amount, y: self.y + amount)
}
mutating func adjustInPlace(amount: CGFloat) -> Void {
x += amount
y += amount
}
}
extension Array where Element: Pointy {
func adjustBy(amount: CGFloat) -> Array<Pointy> {
return self.map { $0.adjustBy(amount: amount) }
}
mutating func adjustInPlace(amount: CGFloat) {
for index in self.indices {
// mysterious chunk of type calculus: need "as! Element" -- https://forums.developer.apple.com/thread/62164
self[index].adjustInPlace(amount: amount) // or self[index] = (self[index].adjustBy(amount: amount)) as! Element
}
}
}
// Hide the above in a Util.swift that noone ever sees.
// AND NOW the true power shows
var points = [ CGPoint(x: 3.0, y: 4.0) ]
points.adjustInPlace(amount: 7.5)
points.forEach { print($0) }
// outputs (10.5, 11.5)
let adjustedPoints = points.adjustBy(amount: 7.5) // Original unchanged