Here's a simple playground example:
class Foobar {
var name = ""
init(name:String) {
self.name = name
}
func modifyName(modification:String) {
self.name += modification
}
}
let list = [Foobar(name:"I"), Foobar(name:"Me"), Foobar(name:"Myself")]
for each in list {
each.modifyName(" rules")
}
A class with name
variable, and a single function that can modify that variable. Make a list of them, now use a for in
to exercise the modifying function.
BUT. If I refactor the modifyName variable into a protocol extension:
class Foobar {
var name = ""
init(name:String) {
self.name = name
}
}
protocol Modifiable {
var name:String { get set }
}
extension Modifiable {
mutating func modifyName(modification:String) {
self.name += modification
}
}
extension Foobar:Modifiable { }
Then the for in
will no longer work because the Modifiable
extension needed to annotate the modifyName
as mutating
. The error emitted is error: cannot use mutating member on immutable value: 'each' is a 'let' constant
. There's a simple workaround, but it feels like I'm abusing something:
for each in list {
var each = each
each.modifyName(" rules")
}
I've had the same problem with functions that have an argument that has been tagged with annotating. It used to be the case that you could mark those parameters with var
in the arg list, but that is deprecated in the latest versions of swift. The same single line workaround works there. Is there a better more idiomatic way to do this? What originally started this, was simply extracting some common behavior into protocol extensions, rather than an inheritance tree. It feels like I'm paying a penalty for that choice.