This implementation falls into a performance trap, as described in the documentation for indices
. Essentially, indices
might hold a reference to self
, in which case mutating self
while iterating over indices
creates an extra copy of self
. In the standard library, this occurs for Dictionary.Values
.
The recommended approach is to manually advance an index.
extension MutableCollection {
mutating func mutateAll(_ f: (inout Element) throws -> ()) rethrows {
var i = startIndex
while i != endIndex {
try f(&self[i])
formIndex(after: &i)
}
}
}
Also, if you want to directly pass in a function (eg. sin
) rather than a closure, then the parameter should not be inout
:
extension MutableCollection {
mutating func mutateAll(_ f: (Element) throws -> Element) rethrows {
var i = startIndex
while i != endIndex {
self[i] = try f(self[i])
formIndex(after: &i)
}
}
}
The difference is in how you call it:
x.mutateAll{ $0 *= $0 } // inout
x.mutateAll{ $0 * $0 } // non-inout
x.mutateAll(sin) // non-inout