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

Jay Abbott jay at abbott.me.uk
Tue Oct 11 06:05:17 CDT 2016


actually scratch point a) - that's bloody obvious :D

On Tue, 11 Oct 2016 at 11:58 Jay Abbott <jay at abbott.me.uk> wrote:

> This is interesting. I'm trying to evaluate your statement that "No setter
> would be needed if a mutation clause is provided" but I can't think exactly
> what the compiler would do in the case where there is a 'get' and 'mutate',
> but no 'set'...
> a) when you call a non-mutating function;
> b) when you assign a new value.
> c) when get and set aren't implemented with a matching hidden var (i.e.
> using a bit in an int var or storing in a dictionary).
>
>
> On Tue, 11 Oct 2016 at 11:26 Tim Vermeulen via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Just having getters and setters doesn’t allow this (unless the optimiser
> is really smart about it). All the current API allows is grabbing whatever
> the `get` clause returns, mutating it, and then passing it into the `set`
> clause, whatever that does. The `set` clause might not do anything, or what
> it does could be seemingly unrelated to the `get` clause, so it’s not a
> trivial task to optimise this.
>
> On 11 Oct 2016, at 06:35, Erica Sadun <erica at ericasadun.com> wrote:
>
>
> On Oct 10, 2016, at 9:53 PM, Tim Vermeulen via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> 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.
>
>
> If this is computationally better, why is it not the default behavior
> rather than an API change?
>
> -- E
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161011/38d44edd/attachment.html>


More information about the swift-evolution mailing list