Swift 容器的易变性浅吗?或者一个元素可以就地改变吗?

Is the mutability of Swift containers shallow? Or can an element be mutated in place?

我在 Set 中有一组对象。对象的类型遵循 GeneratorType,所以我有一个变异方法 next。虽然我可以通过 adding/removing 个元素来改变集合,但我不知道如何改变一个元素。同时使用 for-in 语句和 forEach 方法会给出关于元素不可变的错误。 Swift 容器的易变性是否浅?

有没有办法在包含的元素上调用变异方法?它对 Set 以外的其他 collection/sequence 类型有效吗? (我的更改会更改每个对象的哈希值,也许我不允许这样影响集合。)

这种情况类似于改变一个字典的值,其中该值是一个值类型。你不能这样做,即使你对字典的引用是 var 引用。通常,您只需将值拉出,对其进行变异,然后再放回去:

var d = ["key":"hell"]
var val = d["key"]!
val.append(Character("o"))
d["key"] = val

您的 Set 的工作方式类似。

var s = Set(["hell"])
var val = s.remove("hell")!
val.append(Character("o"))
s.insert(val)

还有其他方法可以表示,但实际上它们是一样的。

这里要记住的是没有值类型,例如一个结构,是 真正 可变的。我们说它好像它是,Swift 和它的 mutating 函数也是如此,但突变实际上包括将一个新值分配回引用。那就是 为什么 引用必须是 var。因此没有这样的东西作为任何值类型的突变。

现在,当然有引用类型,例如一个class,情况就完全不同了:

let s = Set([NSMutableString(string:"hell")])
s.first!.appendString("o")
s // {"hello"}