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

how do people deal with iterating a Swift struct value-type property?

提问人:matt 提问时间:1/3/2019 更新时间:1/3/2019 访问量:205

问:

对于人们来说,这是一个必须一直出现的明显情况:

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())
}

该代码是合法的,但当然它对 没有影响,因为它仍然是一个副本 - 实际的不受影响。fvar ccolumnsf

我毫不费力地理解为什么会这样。我的问题是人们通常对此做些什么

显然,我可以通过将 Column 声明为而不是结构来使整个问题消失,但这是人们通常做的事情吗?(我试图遵循一种心理限制,即当不需要动态调度/多态/子类化时,应该避免类;也许我走得太远了,或者人们通常会做其他事情,比如以某种方式使用。inout

swift for 循环 结构 按值传递

评论

3赞 Hamish 1/3/2019
在Swift论坛(forums.swift.org/t/idea-mutatingforeach-for-collections/18442forums.swift.org/t/in-place-map-for-mutablecollection/11111)上已经讨论过添加“改变每个元素”的方法。但是,我相信最终目标是一旦我们有了适当的所有权模型,就可以在语言级别实现这一点,允许您说类似 .for inout c in f.columns
3赞 Martin R 1/3/2019
我不知道人们通常做什么。我所看到的“解决方法”是迭代索引:for i in f.columns.indices { f.columns[i].cards.append(Card()) }
0赞 matt 1/3/2019
@MartinR 这是一个很好的折衷方案,你愿意给出答案吗?
0赞 matt 1/3/2019
@Hamish搞笑,因为当然我尝试打字,即使我知道它不会编译。:)for inout

答:

2赞 Martin R 1/3/2019 #1

从 Swift 4 开始,折衷方案是遍历可变集合的索引而不是元素本身,以便

for elem in mutableCollection {
    // `elem` is immutable ...
}

for var elem in mutableCollection {
   // `elem` is mutable, but a _copy_ of the collection element ...
}

成为

for idx in mutableCollection.indices {
    // mutate `mutableCollection[idx]` ...
}

在您的示例中:

for idx in f.columns.indices {
   f.columns[idx].cards.append(Card()) 
}

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

for inout elem in mutableCollection {
   // mutate `elem` ...
}

可能。