Reputation: 12552
struct MyStruct {
var count = 0
mutating func add(amount: Int) {
count += amount
}
}
var myStruct = MyStruct()
[1, 2, 3, 4].forEach(myStruct.add)
// Partial application of 'mutating' method is not allowed
Why isn't using forEach
like this allowed for mutating methods? I'm aware that I could do
for number in [1, 2, 3, 4] {
myStruct.add(number)
}
or
[1, 2, 3, 4].forEach { myStruct.add($0) }
instead, but neither are as clean as
[1, 2, 3, 4].forEach(myStruct.add)
Upvotes: 29
Views: 8850
Reputation: 36277
This answer is only related to the error message, but not the code in the question.
I was appending to an array like this:
array.append[newElement]
And that was throwing me two errors:
Partial application of 'mutating' method is not allowed
Value of type '(__owned Int) -> ()' has no subscripts
I was getting the error, because I had to use ()
instead of []
. Basically the first error was misleading to follow. Fixing the 2nd error message, resolved everything
The error went away after changing it to:
array.append(newElement)
Upvotes: 0
Reputation: 57
struct MyStruct {
static var count = 0
var amount: Int
mutating func add() {
MyStruct.count = MyStruct.count + amount
}
}
var array = [1,2,3,4,5,6]
for i in array {
var callfunc = MyStruct(amount: i)
callfunc.add()
}
print(MyStruct.count) // count of list
you can also do it using static var in struct
Upvotes: -1
Reputation: 29468
The key to a value type is that assignment creates a copy. This contract also affects how people can reason about their code. For example if you're passed an Int
into a method, you can be confident that the value won't change out from under you, even if the original int passed in gets sent off to another thread and has calculations done elsewhere.
Same is true for structs. This is why in swift when defining methods that may alter 'self', if it's a value type you have to define it as 'mutating'. What this says is that it will simultaneously reassign to your variable with the new value. So for example When you call your add method with '3', you can think of it performing something similar to:
var myStruct = MyStruct()
var tmp = myStruct
tmp.count = tmp.count + 3
myStruct = tmp
Now the reason that you are hitting an error is because partially applying a mutating function would break that contract. If you are able to save a closure like let myStructAdd = myStruct.add
, then at some later point you could call myStructAdd(3)
and it would try to change myStruct. This would give reference semantics to a value type since now you have the power to alter myStruct at a later point, even from a different method.
In short, swift is giving you a convenience by providing 'mutating' methods for code readability, with the caveat that it has to happen all at once so as not to break the value type contract.
Upvotes: 34