Mutating Functions in Swift Structs

I’ve started working a lot more with Swift Structs, especially as I’m learning more about functional programming. I remember when Swift first came out, I was super confused about why the compiler made me insert the “mutating” keyword for my functions in structs. However, now after reading a bunch about value vs reference types, it’s starting to make a lot of sense.

Throughout this post, I’ll be using a simple Rectangle struct:

struct Rectangle {
    var width = 1
    var height = 1
}

The Mutating Keyword

Let’s say you want to add an area function to your struct:

struct Rectangle {
    var width = 1
    var height = 1
    
    func area() -> Int {
        return width * height
    }
}

It’s just as you expect! This area function multiplies the existing width and height of the rectangle and returns the result. The key here is that this function does NOT change the width or height variables – it only uses the existing values.

In contrast, let’s say we wanted to have a function that scales the rectangle:

struct Rectangle {
    var width = 1
    var height = 1

    mutating func scaleBy(value: Int) {
        width *= value
        height *= value
    }
}

Notice that this function actually changes the width and height variables of the rectangle. So this is where you have to use the mutating keyword – when you’re actually changing the variables in your struct!

Using A Mutating Function

So the first time I wrote a mutating function, I was surprised (and very frustrated) when this happened:

Mutating Function Error Swift

As you can see, this compiler error is super confusing and unhelpful if you don’t fully understand how the mutating concept works.

The “fix” (aka correct way to work with / use mutating functions) is to make your struct a variable:

Struct Variable Swift

Tadaaaa! It magically works! I wonder why…

Why Var?

Remember, a Struct is a value type. In other words, it’s supposed to be immutable. That’s confusing, considering it appears like we’ve added a function that mutates the internals of our struct. Yep, the mutating keyword is starting to make sense now.

By having to make our struct a variable instead of a constant to use the mutating function, Swift is giving us a very strong hint as to what is happening. When we call our mutating scaleBy function, it actually replaces the original rectangle stored in the myRect variable with a brand new rectangle (with the new scaled width and height in our case).

As I was trying to understand this more, I remembered that @jspahrsummers mentioned something on the topic at the Functional Swift Conference. I recommend watching his whole talk, but if you want to get a better understanding of the mutating struct behavior, watch this video starting at the 12:30 mark.

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.