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

Xiaodi Wu xiaodi.wu at gmail.com
Tue Oct 11 10:26:12 CDT 2016


The following document may inform your discussion here:
https://github.com/apple/swift/blob/73841a643c087e854a2f62c7e073317bd43af310/docs/proposals/Accessors.rst


On Tue, Oct 11, 2016 at 6:42 AM, Tim Vermeulen via swift-evolution <
swift-evolution at swift.org> wrote:

> Oh, I see. I’m not sure about the dictionary one, that probably depends on
> whether the `Dictionary` type could use this addition to make member
> mutations O(1). The other example probably wouldn’t benefit from replacing
> the setter by a mutator, as there’s nothing to gain here - the
> implementation is already optional. This is exactly why `set` shouldn’t be
> removed from the language :)
>
> `mutate` wouldn’t be able to replace each and every setter, but there's a
> lot of situations imaginable where it can.
>
>
> On 11 Oct 2016, at 13:20, Jay Abbott <jay at abbott.me.uk> wrote:
>
> In case c) for example if your set implementation was something like this:
> set { _internalDict["propName"] = newValue }
> set { if newValue { _int |= SOME_BIT } else { _int &= ~SOME_BIT } }
> Could they be implemented as 'mutate'?
>
>
> On Tue, 11 Oct 2016 at 12:05 Jay Abbott <jay at abbott.me.uk> wrote:
>
>> 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
>>
>>
>
> _______________________________________________
> 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/fd56282e/attachment.html>


More information about the swift-evolution mailing list