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 :)
actually scratch point a) - that's bloody obvious :D
On Tue, 11 Oct 2016 at 11:58 Jay Abbott <jay@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@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@ericasadun.com> wrote:
On Oct 10, 2016, at 9:53 PM, Tim Vermeulen via swift-evolution < >> swift-evolution@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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution