swiftinfix-operator

Mutating Infix Functions for Structs Swift


So say I have a Vector structure:

struct Vector
{
    var x: Double = 0
    var y: Double = 0

    init(x: Double, y: Double)
    {
        self.x = x
        self.y = y
    }
}

And I create an infix function that adds two Vector structures:

func +(left: Vector, right: Vector) -> Vector
{
    return Vector(left.x + right.x, left.y + right.y)
}

This works well, but then when I want to create an infix function that adds two Vectors together and sets the left value to the result (like +=), then it doesn't work:

func +=(left: Vector, right: Vector)
{
    left.x += right.x
    left.y += right.y
}

When I try it in my code, it doesn't do anything. If I change the Vector structure into a class, then it works.

I know that Swift copies structs and references classes, so is there a way to do this or is this impossible?

Thanks in advance!


Solution

  • In your += function on its current form, you're attempting to mutate members of an immutable value type, which are, themselves, immutable. If you add the inout keyword to left in the function signature, this value type will become mutable and its mutation updated via inout:s copy-in-copy-out behaviour (compiler optimization: in practice by reference to avoid copy overhead, if possible), whereafter your += function will work as intended.

    func +=(left: inout Vector, right: Vector)
    {
        left.x += right.x
        left.y += right.y
    }
    

    The reason your initial function worked for class types is that an the members of an immutable reference type are, themselves, mutable; only the reference itself may not be mutated.