Tim Vermeulen
Tim Vermeulen

Reputation: 12552

Partial application of 'mutating' method is not allowed

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

Answers (3)

mfaani
mfaani

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

Tony wilson jesuraj
Tony wilson jesuraj

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

bobDevil
bobDevil

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

Related Questions