Search code examples
swiftimmutability

Why does this Swift struct require "mutating"?


I am missing something about the mutability concept in Swift. I normally use objects, not structs, to get observability, so the value semantics are still new to me.

struct Game {
  var map: [[Int]]

So here I have declared map as mutable. So why in a method like this...

  mutating func createPlayer() {
    // emptyLocation -> (Int, Int)
    let (X,Y) = emptyLocation()
    map[X][Y] = .player
  }

...do I have to use the mutating? Yes, the function is mutating, but the original struct is declared as such. It seems that practically every func will be mutatingin practice, which seems to defeat the purpose of the markup.

Is there some other way I should be doing this? Is the common use of mutating indicating a performance/memory issue I should be avoiding?

Update: I was rather upset at the way the internal state of the struct "leaked out" to the surrounding code; if you declare a member var inside the struct then it has to be outside as well, even if you never changed. This violates every concept of encapsulation I can think of. So I changed struct to class, removed all the mutating, and was done with it. I get the idea, but I'm not sure I fully understand the implementation. It seems, to this Swift-noob, that the mutating is something the compiler can determine without me telling it - is the member declared var?, does the func actually mutate it? etc.


Solution

  • Yes it is the default behaviour for a struct or enum that instance methods can not modify a property since they are value type. So you need to use mutating to override this behaviour.

    The way you define your property, var or let, is still relevant for if you can change it from a mutable instance method or directly or not.

    Since your property is not private you can still do

    var g = Game(map: [[1]])
    g.map.append([2])