[swift-evolution] [Pitch] Adding a `mutate` clause to computed properties and subscripts

Tim Vermeulen tvermeulen at me.com
Mon Oct 10 22:53:12 CDT 2016


There have been many instances where unexpected bad performance was caused by the interplay between getters, setters, mutations and the copy-on-write mechanism. For example:

struct Foo {
    private var _array: [Int] = [1, 2, 3, 4, 5]
    
    var array: [Int] {
        get { return _array }
        set { _array = newValue }
    }
}

var foo = Foo()
foo.array.append(6) // an O(n) operation

I propose a `mutate` clause which provides a `mutate` function with a single inout parameter (similar to how `set` provides `newValue`), which can be used instead of a setter:

var array: [Int] {
    get { return _array }
    mutate { mutate(&_array) }
}

The compiler could then translate each mutation of `foo.array` to a closure with an inout parameter, which is then passed into the `mutate` clause (which in turn is executed with `_array` as its argument, as per the snippet above). For example, for `foo.array.append(6)`, the compiler would internally generate the closure `{ (arr: inout [Int]) in arr.append(6) }` and pass it into the `mutate` clause, `_array` is then passed as its parameter and the array is updated in constant time.

I apologise if that was too hard to follow.

No setter would be needed if a mutation clause is provided, but I see no good reason to do away with setters altogether, so this proposal would be purely additive.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161011/dc88c649/attachment.html>


More information about the swift-evolution mailing list