Swift Bite – Mutating Functions

Value types such as structures and enumerations can have methods in Swift. These methods may want to modify the properties defined in the types. Consider an example –

struct Stack {
   private var items: [Int] = Array()
}

let stack = Stack()

Here we have defined a struct called Stack which has a property, items.

If we want to write a method to push the item in the Stack, we would write something like –

struct Stack {
   private var items: [Int] = Array()

   mutating func push(item: Int) {
       self.items.append(item) //Error
   }
}

var stack = Stack()
stack.push(item: 10)

The push method above tries to add the item in the items array. This throws an error as we are trying to change the instance property (items) from within the method of the struct. This is not possible inherently as the self is declared as let by default for the value types. This restricts any instance property to be changed from within the value type.

Let’s understand this more. self is inherently passed as a function parameter to every instance method of the type. As self is declared as let by default, there is no way we can mutate the instance (self) or any properties on that instance from within the function.

An alternate way could be – we could create a new instance of the Stack, copy the existing items array and add the new item to the items array.

struct Stack {
  var items: [Int] = Array()

   func push(item: Int) -> Stack {
        var copy = items
        copy.append(item)
        return Stack(items: copy)
   }
}

let stack = Stack()
let newStack = stack.push(item: 10)

This ends up creating a new copy of the struct every time we try to push a new item in the Stack.

mutating keyword

Is there a better solution? Yes! Swift provides a better way to mutate the properties and instance of the value type inherently. A function needs to be marked with the mutating keyword. This makes self passed as an inout variable to the function and let us change its value or the value of any other instance property, provided the property is declared as var. This way we can restrict creating unnecessary copies of the value types, which can be costly sometimes. Code would look like this now –

struct Stack {
  private var items: [Int] = Array()

   mutating func push(item: Int) {
       self.items.append(item) // Works fine! self is passed as an inout variable here
   }
}

var stack = Stack()
stack.push(item: 10)

Point to note – Mark a function as mutating if you want to mutate/change the value type instance or its properties from within the function.

2 thoughts on “Swift Bite – Mutating Functions

  1. I think there are two errors in your last code block:
    1. `let stack = Stack()` should be `var stack = Stack()`, or your mutating method won’t work.
    2. `let newStack = stack.push(item: 10)` should be `stack.push(item: 10)`, since stack.push() doesn’t return anything.

    Like

    1. Made the correction. Thanks for pointing out.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: