Conceptual questions about Struct's immutability and property changes from within the struct and from the instance

struct Test {
var a: Int

func changeA() {
    a = 10
}

}

var testInstance = Test(a: 10)
testInstance.a = 1

1.- I understand, Structs are immutable, nonetheless the Swift compiler allows me to change Property “a” to 1, after it was already initialized to 10, were Structs immutable? why this is allowed?

2.- If the Swift compiler allows to change property “a” from the instance, why it doesn’t allow to have the method “changeA” to modify “a” from within the Struct without adding the “mutating” modifier? It seems it is allowed to modify the property from the instance, but not from a method within the Struct, why?

3.- These are more conceptual questions, I fully understand that I can add “mutating” in front of the method and it will compile, but why I have to do that, if by default I am allowed to modify the property from outside the method after initialization, why the extra level of rigor with “mutating” to modify a property, that it is already declared as “var”?

I am very much interested in the theory and concepts behing Struct’s immutability, thank you very much for your help.

@logi You can change the value of the a property in this case because the testInstance object is defined as a variable.

Declare the testInstance object as a constant instead in order to make it immutable like this:

let testInstance = Test(a: 10)
testInstance.a = 1

The compiler flags the following error for the above code:

Cannot assign to property: `testInstance` is a `let` constant.

You can’t change the value of the a property this time since the testInstance object is immutable.

The same thing happens for the changeA() method in this case as follows:

func changeA() {
  a = 10
}

The compiler flags the following error for the above code:

 Cannot assign to property: `self` is immutable.

You can’t change the value of the a property this time because the self object is defined as a constant inside the changeA() method by default.

The compiler always adds the self object to the changeA() method under the hood like this:

func changeA() {
  self.a = 10
}

Use the mutating keyword in order to declare the self object as a variable inside the changeA() method instead as follows:

mutating func changeA() {
  a = 10
}

The self object is mutable inside the changeA() method in this case.

The compiler still adds the self object to the changeA() method under the hood like this:

mutating func changeA() {
  self.a = 10
}

The changeA() method behaves exactly like the a property this time as follows:

let testInstance = Test(a: 10)
testInstance.changeA()

The compiler flags the following error for the above code:

Cannot use mutating member on immutable value: `testInstance` is a let constant.

You can’t call the changeA() method in this case since the testInstance object is immutable.

Define the testInstance object as a variable instead in order to make it mutable like this:

var testInstance = Test(a: 10)
testInstance.changeA()

You can call the changeA() method this time because the testInstance object is mutable.

Please let me know if you have any more questions or other issues about the whole thing when you get a chance. Thank you!

Thank you very much for the detailed explanation, it is much clearer now

1 Like

This topic was automatically closed after 166 days. New replies are no longer allowed.