Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial application of 'mutating' method is not allowed

Tags:

swift

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) 
like image 265
Tim Vermeulen Avatar asked May 27 '16 16:05

Tim Vermeulen


1 Answers

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.

like image 122
bobDevil Avatar answered Sep 28 '22 04:09

bobDevil