What is the difference between let and var in Apple\'s Swift language?
In my understanding, it is a compiled language but it does not check
let is used to define constants and var to define variables.
let - constant
var - variable
[Constant vs variable]
[Struct vs Class]
Official doc docs.swift.org says
The value of a
constantcan’t be changed once it’s set, whereas avariablecan 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]
 
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 FunctionsYou can mark a struct's method as mutating
var variablefunc 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 functioninout allows you to reassign/modify a passed(original) value.var variable inside inout parameterinout has  a next flow:
//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
letwhenever you can. Usevarwhen you must.
[Mutate structure]
Very simple:
let is constant. var is dynamic.Bit of description:
let creates a constant. (sort of like an NSString). You can't change its value once you have set it. You can still add it to other things and create new variables though.
var creates a variable. (sort of like NSMutableString) so you can change the value of it. But this has been answered several times.
The
Declaring Constants and Variables section of The Swift Programming Language documentation specifies the following:
You declare constants with the let keyword and variables with the var keyword.
Make sure to understand how this works for Reference types. Unlike Value Types, the object's underlying properties can change despite an instance of a reference type being declared as a constant. See the Classes are Reference Types section of the documentation, and look at the example where they change the frameRate property.
The main difference is that var variable value can change, and let can't. If you want to have a user input data, you would use var so the value can be changed and use let datatype variable so the value can not be changed. 
var str      = "dog"  // str value is "dog"
str          = "cat"  // str value is now "cat"
let strAnimal = "dog" // strAnimal value is "dog"
strAnimal     = "cat" // Error !
Though currently I am still reading the manual, but I think this is very close to C/C++ const pointer. In other words, something like difference between char const* and char*. Compiler also refuses to update content, not only reference reassignment (pointer).
For example, let's say you have this struct. Take care that this is a struct, not a class. AFAIK, classes don't have a concept of immutable state.
import Foundation
struct
AAA
{
    var inner_value1    =   111
    mutating func
    mutatingMethod1()
    {
        inner_value1    =   222
    }
}
let aaa1    =   AAA()
aaa1.mutatingMethod1()      // compile error
aaa1.inner_value1 = 444     // compile error
var aaa2    =   AAA()
aaa2.mutatingMethod1()      // OK
aaa2.inner_value1 = 444     // OK
Because the structs are immutable by default, you need to mark a mutator method with mutating. And because the name aaa1 is constant, you can't call any mutator method on it. This is exactly what we expected on C/C++ pointers.
I believe this is a mechanism to support a kind of const-correctness stuff.