Swift for in - 获取条目作为引用

标签 swift for-loop pass-by-reference

有没有办法让 for .. in 循环返回对集合条目的引用而不是副本

假设我有一个 CGPoint 对象的数组 points,我想遍历它们并将每个点传递给一个函数 adjustPoint,它可以使用 inout 参数修改点。

现在执行以下操作不起作用,因为 for .. 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 .. in 循环?

注意:我读过很久以前的这个问题(我相信是 Swift 1)所以我想也许他们同时改变了一些东西:turn for in loops local variables into mutable variables

最佳答案

所以你原来的基本答案 for循环问题是:没有。 for...in旨在为您提供值类型的副本。正如您在评论中所说,这是一种强制函数式编程风格。

要改变一个数组,你必须说 array[index]以某种方式,现在您指的是原始值并且可以改变它。诀窍是找到一种可以防止常见错误的表达方式。我在下面提倡的四种技术是:

  1. 做一个强大的抽象 extension所以你在整个代码中干
  2. 使用indices不是手动范围,也容易出错( .....< )
  3. 避免像 & 这样丑陋的 C 语言结构(见#1)
  4. 考虑保留变异版本和非变异版本

这可能最符合 Swift 的精神,即古怪、冗长且比您想要的更烦人,但最终在适当的层到位的情况下非常具有表现力和功能:

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

关于Swift for in - 获取条目作为引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39707845/

相关文章:

ios - 在 ViewWillDisappear 上插入数据库

python - 使用 tkinter 在带有 for 语句的标签中显示图片,可以做到吗?

c - 通过引用和扫描值传递矩阵

swift - vapor 中的异步执行。如何控制in的循环

swift - 在 Swift 中将 switch 转换为 if else

java - 将 StringBuilder 内容“传输”到 java 中的新 ArrayList

在for循环中具有三个值的Python dict

javascript - typescript (Angular2): Passing objects to functions -> possible memory leaks?

c - 我在使用字符串通过引用传递时遇到问题

swift - 变量值为空。为什么?