let - constant

var - variable

[Constant vs variable]

[Struct vs Class]

Official doc docs.swift.org says

The value of a constant can’t be changed once it’s set, whereas a variable can be set to a different value in the future.

This terminology actually describes a reassign mechanism

Mutability

Mutability - changeable - object's state can be changed after creation[About]

Value and Reference Type[About]

Reference Type(Class)

Swift's classes are mutable a-priory

var + class

It can be reassigned or changed

let + class = constant of address

It can not be reassigned and can be changed

Value(Struct, Enum)

Swift's struct can change their mutability status:

var + struct = mutable

It can be reassigned or changed

let + struct = *immutable = constant of value

It can not be reassigned or changed

*immutable - check testStructMutability test

Experiments:

class MyClass { var varClass: NSMutableString var varStruct: String let letClass: NSMutableString let letStruct: String init(_ c: NSMutableString, _ s: String) { varClass = c varStruct = s letClass = c letStruct = s } } struct MyStruct { var varClass: NSMutableString var varStruct: String let letClass: NSMutableString let letStruct: String init(_ c: NSMutableString, _ s: String) { varClass = c varStruct = s letClass = c letStruct = s } //mutating function block func function() { // varClass = "SECONDARY propertyClass" //Cannot assign to property: 'self' is immutable // varStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'self' is immutable } mutating func mutatingFunction() { varClass = "SECONDARY propertyClass" varStruct = "SECONDARY propertyStruct" } }

Possible use cases

func functionVarLetClassStruct() { var varMyClass = MyClass("propertyClass", "propertyStruct") varMyClass.varClass = "SECONDARY propertyClass" varMyClass.varStruct = "SECONDARY propertyStruct" // varMyClass.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant // varMyClass.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant let letMyClass = MyClass("propertyClass", "propertyStruct") letMyClass.varClass = "SECONDARY propertyClass" letMyClass.varStruct = "SECONDARY propertyStruct" // letMyClass.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant // letMyClass.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant var varMyStruct = MyStruct("propertyClass", "propertyStruct") varMyStruct.varClass = "SECONDARY propertyClass" varMyStruct.varStruct = "SECONDARY propertyStruct" // varMyStruct.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant // varMyStruct.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant let letMyStruct = MyStruct("propertyClass", "propertyStruct") // letMyStruct.varClass = "SECONDARY propertyClass" //Cannot assign to property: 'letMyStruct' is a 'let' constant // letMyStruct.varStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letMyStruct' is a 'let' constant // letMyStruct.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant // letMyStruct.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant }

mutating - Mutating Struct's Functions

You can mark a struct's method as mutating



Indicates that this function changes internal property values You are only able to call mutating function on var variable Result is visible when mutating function is finished

func testStructMutatingFunc() { //given var varMyStruct = MyStruct("propertyClass", "propertyStruct") //when varMyStruct.mutatingFunction() //than XCTAssert(varMyStruct.varClass == "SECONDARY propertyClass" && varMyStruct.varStruct == "SECONDARY propertyStruct") // It is not possible to call a mutating function on a let variable let letMyStruct = MyStruct("propertyClass", "propertyStruct") // letMyStruct.mutatingFunction() //Cannot use mutating member on immutable value: 'letMyStruct' is a 'let' constant }

inout inside a function

inout allows you to reassign/modify a passed(original) value. You are only able to pass var variable inside inout parameter Result is visible when function is finished

inout has a next flow:

passed value is copied into copied value before a function called copied value is assign into passed value after the function finished

//InOut func functionWithInOutParameter(a: inout MyClass, s: inout MyStruct) { a = MyClass("SECONDARY propertyClass", "SECONDARY propertyStruct") //<-- assign s = MyStruct("SECONDARY propertyClass", "SECONDARY propertyStruct") //<-- assign } func testInOutParameter() { //given var varMyClass = MyClass("PRIMARY propertyClass", "PRIMARY propertyStruct") var varMyStruct = MyStruct("PRIMARY propertyClass", "PRIMARY propertyStruct") //when functionWithInOutParameter(a: &varMyClass, s: &varMyStruct) //then XCTAssert(varMyClass.varClass == "SECONDARY propertyClass" && varMyClass.varStruct == "SECONDARY propertyStruct") XCTAssert(varMyStruct.varClass == "SECONDARY propertyClass" && varMyStruct.varStruct == "SECONDARY propertyStruct") // It is not possible to pass let into inout parameter let letMyClass = MyClass("PRIMARY propertyClass", "PRIMARY propertyStruct") let letMyStruct = MyStruct("PRIMARY propertyClass", "PRIMARY propertyStruct") // functionWithInOutParameter(a: &letMyClass, s: &letMyStruct) //Cannot pass immutable value as inout argument: 'letMyClass', 'letMyStruct' are 'let' constants }

*You steal are able to mutate let + struct

func testStructMutability() { //given let str: NSMutableString = "propertyClass" let letMyStruct = MyStruct(str, "propertyStruct") //when str.append(" SECONDARY") //then XCTAssert(letMyStruct.letClass == "propertyClass SECONDARY") }