Swift let vs var
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 or rather unmodifiable[About] [Example] [Example] = 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 varvariable
- 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
- inoutallows you to reassign/modify a passed(original) value.
- You are only able to pass varvariable insideinoutparameter
- 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")
}
Use let whenever you can. Use var when you must.
[Mutate structure]