人们如何处理迭代Swift结构值类型属性?

mat*_*att 7 struct for-loop pass-by-value swift

这是一个明显的情况,必须始终为人们出现:

struct Foundation {
    var columns : [Column] = [Column(), Column()]
}
struct Column : CustomStringConvertible {
    var cards = [Card]()
    var description : String {
        return String(describing:self.cards)
    }
}
struct Card {}
var f = Foundation()
for var c in f.columns {
    c.cards.append(Card())
}
Run Code Online (Sandbox Code Playgroud)

该代码是合法的,但当然这有没有影响f,因为var c仍然是一个副本-实际columnsf不受影响.

理解为什么这样,我没有任何困难.我的问题是人们通常对此做些什么.

显然,我可以通过将Column声明为一个而不是一个结构来让所有事情消失,但这是人们通常做的事情吗?(我正试图遵循一个心理上的限制,即当不需要动态调度/多态/子类化时,应该避免上课;也许我带着太多的东西,或者也许人们通常会做其他事情,比如以inout某种方式使用.)

Mar*_*n R 2

从 Swift 4 开始,一种折衷方案是迭代可变集合的索引而不是元素本身,这样

for elem in mutableCollection {
    // `elem` is immutable ...
}
Run Code Online (Sandbox Code Playgroud)

或者

for var elem in mutableCollection {
   // `elem` is mutable, but a _copy_ of the collection element ...
}
Run Code Online (Sandbox Code Playgroud)

变成

for idx in mutableCollection.indices {
    // mutate `mutableCollection[idx]` ...
}
Run Code Online (Sandbox Code Playgroud)

在你的例子中:

for idx in f.columns.indices {
   f.columns[idx].cards.append(Card()) 
}
Run Code Online (Sandbox Code Playgroud)

正如 @Hamish 在评论中指出的那样,Swift 的未来版本可能会实现变异迭代,使得

for inout elem in mutableCollection {
   // mutate `elem` ...
}
Run Code Online (Sandbox Code Playgroud)

可能的。