How to safely vend a mutable view on a collection?

how do you provide a mutable view over a collection without risking COW? i tried looking for inspiration from the source of Dictionary.Values, but i couldn’t really understand why it’s written the way it’s written:

  @inlinable
  @available(swift, introduced: 4.0)
  public var values: Values {
    // FIXME(accessors): Provide a _read
    get {
      return Values(_dictionary: self)
    }
    _modify {
      var values = Values(_variant: _Variant(dummy: ()))
      swap(&values._variant, &_variant)
      defer { self._variant = values._variant }
      yield &values
    }
  }

This implementation makes perfect sense. It essentially removes the contents out of the dictionally into a local variable, making sure that the local variable is the only copy, then the local variable is modified, then the local variable is put back into the dictionary. That way the contents are not going to be copied. Furthermore, to avoid making intermediate copies during modification of individual values, the _modify accessor is used instead of set. The way it works is by providing a single-yield coroutine, where the calling context temporarily gets the inout contents. After the yield statement the modification is finished and the contents can be put back into the dictionary. However, because the calling context may throw an error, writing the contents back to the dictionary after the yield statements may never happen, so it has to be put into a defer block to ensure correct behavior regardless of the control flow.

2 Likes