swiftmethodsextension-methodsmutating-function

why mutating method applied on instance doesn't save changes? swift


I extend my custom protocol with mutable function. And then apply it on the instance of the corresponding type. But instance is changed only on that row. On the next row, it has previous value. Why changes made on the instance doesn't persist?

If I assign the result of mutating to the var/let. Then the result saves. Or if I apply harderWorkout() in the print() statement it print changed value.

struct Workout {
    var distance: Double
    var time: Double
    var averageHR: Int
}

extension Workout: CustomStringConvertible {
    var description: String {
        return "Workout(distance: \(distance), time: \(time), averageHR: \(averageHR)"
    }
}

extension Workout {

    mutating func harderWorkout() -> Workout {
    return Workout(distance: (self.distance * 2), time: (self.time * 2), averageHR: (self.averageHR + 40))

    }
}

var workout = Workout(distance: 500, time: 50, averageHR: 100)
print(workout) //Workout(distance: 500.0, time: 50.0, averageHR: 100, Speed: 10.0
workout.harderWorkout()
print(workout) //Workout(distance: 500.0, time: 50.0, averageHR: 100, Speed: 10.0

In the last print I expected to see Workout(distance: 1000.0, time: 100.0, averageHR: 140 but it's not clear to me why harderWorkout() method doesn't change the workout instance. Maybe it's because of the value type. But I put the mutable prefix... Will be very thankful if someone explains to me the reason and its mechanism.


Solution

  • Instead of returning Workout instance from harderWorkout() method, assign the new Workout instance to self, i.e.

    extension Workout {
        mutating func harderWorkout() {
            self = Workout(distance: (self.distance * 2), time: (self.time * 2), averageHR: (self.averageHR + 40))
        }
    }
    

    Alternatively, you can simply change the distance, time and averageHR values of the same instance, i.e.

    extension Workout {
        mutating func harderWorkout() {
            self.distance *= 2
            self.time *= 2
            self.averageHR += 40
        }
    }