What is the advantage of closure stored property Initialisation? - swift

What is the difference and the advantages/disadvantages of this code when initialising a property of a class as:
1.
let menuBar:MenuBar = {
let mb = MenuBar()
return mb
}()
and:
2.
let menuBar = MenuBar()

Both of the code snippets declare and initialize stored properties, but in the first one it is initialized by closure. The reason why you should set a stored property with a closure is: there is a requirement(s) to do customization (calling a method for instance); Adapted from The Swift Programming Language (Swift 4.1) - Initialization: Setting a Default Property Value with a Closure or Function:
If a stored property’s default value requires some customization or
setup, you can use a closure or global function to provide a
customized default value for that property. Whenever a new instance of
the type that the property belongs to is initialized, the closure or
function is called, and its return value is assigned as the property’s
default value.
Which means that you would be able to do:
let menuBar:MenuBar = {
let mb = MenuBar()
// for example, you'd need to call "doSomething" method
// before returning the instance:
menuBar.doSomething()
return mb
}()
Note that in the body of the stored property closure, you would be not able to able to use the other properties in your class/struct since they considered as not being initialized yet. Example:
struct MyType {
let myString = "My String!"
let myInt: Int = {
let anInt = 101
// this won't work
print(myString)
return anInt
}()
}
The result of the above code snippet is getting a compile-time error:
error: instance member 'myString' cannot be used on type 'MyType'
print(myString)
Furthermore at some point, it would be recommended to declare your property as lazy:
lazy var menuBar:MenuBar = {
let mb = MenuBar()
// for example, you'd need to call "doSomething" method
// before returning the instance:
menuBar.doSomething()
return mb
}()
Means that:
A lazy stored property is a property whose initial value is not
calculated until the first time it is used. You indicate a lazy stored
property by writing the lazy modifier before its declaration.

Related

Constant property can be modified during initialization? MODIFIED? What?

Quote from the Swift 3.0 office document of the Chapter: Initialization
For class instances, a constant property can be modified during initialization only by the class that introduces it. It cannot be modified by a subclass.
To my understanding the modified involves the action after the definition, aka the action after declaring and assigning value, aka re-assigning values, therefore I tried the following code.
class SurveryQuestion {
let text: String
var response: String?
init(text: String) {
self.text = "do you like music?"
self.text = text //Got an error here
}
func ask(){
print(text)
}
}
And I got an error at line self.text = text. The compiler asked me to change the property textfrom constant to variable. Isn't it says that the constant property can be modified by the initializer of the class which originally introduced it?
Question: Am I understand the word modified wrongly? Is it means the action after the declaring rather than the definition which would lead to the modified is meant to by passing a value to the constant.
I think that the documentation is not clear enough. You can set a constant property only once during initializing. You also would not be able to set it during initialization if the property's value was defined inline. Here is example.
class SomeClass {
let someProperty: String = "A"
init() {
self.someProperty = "" //ERROR: Immutable value "self.someProperty" may only be initialized once.
}
}
The compile time error //ERROR: Immutable value "self.someProperty" may only be initialized once. actually explains it well.

Capturing a struct reference in a closure doesn't allow mutations to occur

I am trying to see if I can use structs for my model and was trying this. When I call vm.testClosure(), it does not change the value of x and I am not sure why.
struct Model
{
var x = 10.0
}
var m = Model()
class ViewModel
{
let testClosure:() -> ()
init(inout model: Model)
{
testClosure =
{
() -> () in
model.x = 30.5
}
}
}
var vm = ViewModel(model:&m)
m.x
vm.testClosure()
m.x
An inout argument isn't a reference to a value type – it's simply a shadow copy of that value type, that is written back to the caller's value when the function returns.
What's happening in your code is that your inout variable is escaping the lifetime of the function (by being captured in a closure that is then stored) – meaning that any changes to the inout variable after the function has returned will never be reflected outside that closure.
Due to this common misconception about inout arguments, there has been a Swift Evolution proposal for only allowing inout arguments to be captured by #noescape closures. As of Swift 3, your current code will no longer compile.
If you really need to be passing around references in your code – then you should be using reference types (make your Model a class). Although I suspect that you'll probably be able to refactor your logic to avoid passing around references in the first place (however without seeing your actual code, it's impossible to advise).
(Edit: Since posting this answer, inout parameters can now be compiled as a pass-by-reference, which can be seen by looking at the SIL or IR emitted. However you are unable to treat them as such due to the fact that there's no guarantee whatsoever that the caller's value will remain valid after the function call.)
Instances of the closure will get their own, independent copy of the captured value that it, and only it, can alter. The value is captured in the time of executing the closure. Let see your slightly modified code
struct Model
{
var x = 10.0
mutating func modifyX(newValue: Double) {
let this = self
let model = m
x = newValue
// put breakpoint here
//(lldb) po model
//▿ Model
// - x : 30.0
//
//(lldb) po self
//▿ Model
// - x : 301.0
//
//(lldb) po this
//▿ Model
// - x : 30.0
}
}
var m = Model()
class ViewModel
{
let testClosure:() -> ()
init(inout model: Model)
{
model.x = 50
testClosure =
{ () -> () in
model.modifyX(301)
}
model.x = 30
}
}
let mx = m.x
vm.testClosure()
let mx2 = m.x
Here is what Apple says about that.
Classes and Structures
A value type is a type that is copied when it is assigned to a
variable or constant, or when it is passed to a function. [...] All
structures and enumerations are value types in Swift
Methods
Structures and enumerations are value types. By default, the properties of a value type cannot be modified from within its instance methods.
However, if you need to modify the properties of your structure or
enumeration within a particular method, you can opt in to mutating
behaviour for that method. The method can then mutate (that is,
change) its properties from within the method, and any changes that it
makes are written back to the original structure when the method ends.
The method can also assign a completely new instance to its implicit
self property, and this new instance will replace the existing one
when the method ends.
Taken from here

Are computed properties evaluated every time they are accessed?

I have two questions about computed properties in Swift.
Are computed properties evaluated every time they are accessed? Or they are stored somewhere for future access?
What kind of property is this, since I couldn't google it out:
let navigationController: UINavigationController = {
var navigator = UINavigationController()
navigator.navigationBar.translucent = false
return navigator
}()
Is this also evaluated every time it is accessed?
That is NOT a computed property.
let navigationController: UINavigationController = {
var navigator = UINavigationController()
navigator.navigationBar.translucent = false
return navigator
}()
It is just a stored property populated with the result of the value returned by this block of code.
var navigator = UINavigationController()
navigator.navigationBar.translucent = false
return navigator
The block is executed when the instance of the class is instantiated. Only once.
So writing this
struct Person {
let name: String = {
let name = "Bob"
return name
}() // <- look at these
}
is equivalent to this
struct Person {
let name: String
init() {
self.name = "Bob"
}
}
IMHO the first approach is better because:
it does allow you to declared and populate a property in the same "space"
it's more clear
does prevent duplication of code if you have multiple initializers
Note #1: Storing a closure inside a property
As dfri noted in the comment below, the block of code does end with (). It means that the code is evaluated and the result assigned to the property.
On the other hand, if we remove the () at the end of the block, we get something different, infact the block is not evaluated.
In this case Swift tries to assign a stored closure to the property. This will produce a compile error since the property has this type UINavigationController.
With the correct syntax we can put a closure inside a property.
struct Person {
let sayHello: ()->() = { print("Hello") }
}
Now we have a sayHello property which contains a closure. The closure receives 0 parameters and does return Void.
let bob = Person()
bob.sayHello // this does NOT execute the code inside closure
bob.sayHello() // this does execute the code in the closure and does print the message
Note #2: let's talk about Computed Properties
So we made clear that code in this question is not a Computed Property.
However, as EmilioPelaez noted in another comment below, we should also state that a Computed Property is evaluated each time it is accessed.
In the example below I created a Computed Property age. As you can see each time I invoke it, the code in the block gets executed as well.
Example of a Computed Property (age)

Difference between computed property and property set with closure

I'm new to Swift. What is the difference between a computed property and a property set to a closure? I know a computed property gets recalculated each time. Is it different for the closure? i.e.
Closure:
var pushBehavior: UIPushBehavior = {
let lazilyCreatedPush = UIPushBehavior()
lazilyCreatedPush.setAngle(50, magnitude: 50)
return lazilyCreatedPush
}()
Computed:
var pushBehavior: UIPushBehavior {
get{
let lazilyCreatedPush = UIPushBehavior()
lazilyCreatedPush.setAngle(50, magnitude: 50)
return lazilyCreatedPush
}
}
In short, the first is a stored property that is initialized via a closure, with that closure being called only one time, when it is initialized. The second is a computed property whose get block is called every time you reference that property.
The stored property’s initialization closure is called once and only once, but you can later change the value of the stored property (unless you replace var with let). This is useful when you want to encapsulate the code to initialize a stored property in a single, concise block of code.
The computed property’s block, however, is called each time you reference the variable. It’s useful when you want the code to be called every time you reference the computed property. Generally you do this when the computed property needs to be recalculated every time you reference the stored property (e.g. recalculated from other, possibly private, stored properties).
In this case, you undoubtedly want the stored property (the first example), not the computed property (the second example). You presumably don't want a new push behavior object each time you reference the variable.
By the way, in your first example, you internally reference to it being instantiated lazily. If you want that behavior, you must use the lazy keyword:
lazy var pushBehavior: UIPushBehavior = {
let behavior = UIPushBehavior()
behavior.setAngle(50, magnitude: 50)
return behavior
}()
If, however, the property is static, it is automatically instantiated lazily.
Closure :
//closure
var pushBehavior: UIPushBehavior = {
let lazilyCreatedPush = UIPushBehavior()
lazilyCreatedPush.setAngle(50, magnitude: 50)
return lazilyCreatedPush
}()
At first time when pushBehavior variable called then block execute and value is saved in pushBehavior variable. after that whenever you call pushBehavior then those value are returned.
means only first-time block code executed and saved in this variable.
Also, you can store variable value whenever you want but after that, those value returned but if you declare as "let" then you can't change this value.
Computed property :
var pushBehavior: UIPushBehavior {
get{
let lazilyCreatedPush = UIPushBehavior()
lazilyCreatedPush.setAngle(50, magnitude: 50)
return lazilyCreatedPush
}
}
In computed property whenever you called pushBehavior variable then this block execute and value return. so every time block is executed.
and you can not declare variable as "let" keyword for pushBehavior variable.
So you can use this code as per your requirement.
The main difference is that you cannot assign something to the computed property since it has no setter. In this case the closure only gets called once and the return value gets stored in the variable so if the outcome doesn't change over time it is more efficient to use the stored variable rather than the computed one.
In general: computed properties should only be used if the value can be retrieved quickly.
Sidenote: If you don't change/reassign the stored variable you should consider making it a constant (let)
This isn't an answer, but it's just worth mentioning that for:
A stored property's value must be known after initializing completes. That happens either by defaulting or through initialization.
A computed property's value isn't computed until it's accessed
A lazy loaded property's value isn't defined until it's accessed
Hence for both computed and lazy variables you can access self or stored properties with no worries.

What is the difference between `let` and `var` in Swift?

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 the type at compile time. It makes me confused. How does the compiler know about the type error? If the compiler doesn't check the type, isn't it a problem with production environment?
This error is given when I try to assign a value to a let:
Cannot assign to property: 'variableName' is a 'let' constant
Change 'let' to 'var' to make it mutable
The let keyword defines a constant:
let theAnswer = 42
The theAnswer cannot be changed afterwards. This is why anything weak can't be written using let. They need to change during runtime and you must be using var instead.
The var defines an ordinary variable.
What is interesting:
The value of a constant doesn’t need to be known at compile time, but you must assign the value exactly once.
Another strange feature:
You can use almost any character you like for constant and variable
names, including Unicode characters:
let 🐶🐮 = "dogcow"
Excerpts From: Apple Inc. “The Swift Programming Language.” iBooks. https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewBook?id=881256329
Community Wiki
Because comments are asking for adding other facts to the answer, converting this to community wiki answer. Feel free edit the answer to make it better.
According to The Swift Programming Language Book
Like C, Swift uses variables to store and refer to values by an
identifying name. Swift also makes extensive use of variables whose
values cannot be changed. These are known as constants, and are much
more powerful than constants in C.
Both var and let are references, therefore let is a const reference.
Using fundamental types doesn't really show how let is different than const.
The difference comes when using it with class instances (reference types):
class CTest
{
var str : String = ""
}
let letTest = CTest()
letTest.str = "test" // OK
letTest.str = "another test" // Still OK
//letTest = CTest() // Error
var varTest1 = CTest()
var varTest2 = CTest()
var varTest3 = CTest()
varTest1.str = "var 1"
varTest2.str = "var 2"
varTest3 = varTest1
varTest1.str = "var 3"
varTest3.str // "var 3"
let is used to define constants and var to define variables.
Like C, Swift uses variables to store and refer to values by an identifying name. Swift also makes extensive use of variables whose values can’t be changed. These are known as constants, and are much more powerful than constants in C. Constants are used throughout Swift to make code safer and clearer in intent when you work with values that don’t need to change.
https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html
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 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")
}
Use let whenever you can. Use var when you must.
[Mutate structure]
It's maybe better to state this difference by the Mutability / Immutability notion that is the correct paradigm of values and instances changeability in Objects space which is larger than the only "constant / variable" usual notions.
And furthermore this is closer to Objective C approach.
2 data types: value type and reference type.
In the context of Value Types:
'let' defines a constant value (immutable). 'var' defines a changeable value (mutable).
let aInt = 1 //< aInt is not changeable
var aInt = 1 //< aInt can be changed
In the context of Reference Types:
The label of a data is not the value but the reference to a value.
if aPerson = Person(name:Foo, first:Bar)
aPerson doesn't contain the Data of this person but the reference to the data of this Person.
let aPerson = Person(name:Foo, first:Bar)
//< data of aPerson are changeable, not the reference
var aPerson = Person(name:Foo, first:Bar)
//< both reference and data are changeable.
eg:
var aPersonA = Person(name:A, first: a)
var aPersonB = Person(name:B, first: b)
aPersonA = aPersonB
aPersonA now refers to Person(name:B, first: b)
and
let aPersonA = Person(name:A, first: a)
let aPersonB = Person(name:B, first: b)
let aPersonA = aPersonB // won't compile
but
let aPersonA = Person(name:A, first: a)
aPersonA.name = "B" // will compile
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.
let defines a "constant". Its value is set once and only once, though not necessarily when you declare it. For example, you use let to define a property in a class that must be set during initialization:
class Person {
let firstName: String
let lastName: String
init(first: String, last: String) {
firstName = first
lastName = last
super.init()
}
}
With this setup, it's invalid to assign to firstName or lastName after calling (e.g.) Person(first:"Malcolm", last:"Reynolds") to create a Person instance.
You must define a type for all variables (let or var) at compile time, and any code that attempts to set a variable may only use that type (or a subtype). You can assign a value at run time, but its type must be known at compile time.
let is used to declare a constant value - you won't change it after giving it an initial value.
var is used to declare a variable value - you could change its value as you wish.
One more difference, which I've encountered in other languages for Constants is : can't initialise the constant(let) for later , should initialise as you're about to declare the constant.
For instance :
let constantValue : Int // Compile error - let declarations require an initialiser expression
Variable
var variableValue : Int // No issues
let is used to define constants and var to define variables.
You define the string using var then particular String can be modified (or mutated) by assigning it to a variable (in which case it can be modified), and if you define the string using let its a constant (in which case it cannot be modified):
var variableString = "Apple"
variableString += " and Banana"
// variableString is now "Apple and Banana"
let constantString = "Apple"
constantString += " and another Banana"
// this reports a compile-time error - a constant string cannot be modified
in swift language let is a constant means is can not reassign but var can be reassigned
let question = "what is the difference between let and var?"
question = "another question" // this line cause syntax error
var answer = "let is constant and var is simple variable"
answer = "let can't be reassigned var can be reassigned" // this line will be excecuted
let keyword defines a constant
let myNum = 7
so myNum can't be changed afterwards;
But var defines an ordinary variable.
The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once.
You can use almost any character you like for constant and variable names, including Unicode characters;
e.g.
var x = 7 // here x is instantiated with 7
x = 99 // now x is 99 it means it has been changed.
But if we take let then...
let x = 7 // here also x is instantiated with 7
x = 99 // this will a compile time error
Like Luc-Oliver, NullData, and a few others have said here, let defines immutable data while var defines mutable data. Any func that can be called on the variable that is marked mutating can only be called if it is a var variable (compiler will throw error). This also applies to func's that take in an inout variable.
However, let and var also mean that the variable cannot be reassigned. It has two meanings, both with very similar purposes
var value can be change, after initialize. But let value is not be change, when it is intilize once.
In case of var
function variable() {
var number = 5, number = 6;
console.log(number); // return console value is 6
}
variable();
In case of let
function abc() {
let number = 5, number = 6;
console.log(number); // TypeError: redeclaration of let number
}
abc();
Everyone has pretty much answered this but here's a way you can remember what's what
Let will always say the same think of "let" as let this work for once and always as for "var" variable's can always change hence them being called variable's
The keyword var is used to define a variable whose value you can easily change like this:
var no1 = 1 // declaring the variable
no1 = 2 // changing the value since it is defined as a variable not a constant
However, the let keyword is only to create a constant used when you do not want to change the value of the constant again. If you were to try changing the value of the constant, you will get an error:
let no2 = 5 // declaring no2 as a constant
no2 = 8 // this will give an error as you cannot change the value of a constant
Let is an immutable variable, meaning that it cannot be changed, other languages call this a constant. In C++ it you can define it as const.
Var is a mutable variable, meaning that it can be changed. In C++ (2011 version update), it is the same as using auto, though swift allows for more flexibility in the usage. This is the more well-known variable type to beginners.
let is a constant value, so it can never be changed.
let number = 5
number = 6 //This will not compile.
Var is a variable, and can change (but after it is defined not to a different data type.)
var number = 5
number = 6 //This will compile.
If you try changing the variable to a different dataType, it will not work
var number = 5
number = "Hello World" //This will not compile.
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 !
A value can be reassigned in case of var
//Variables
var age = 42
println(age) //Will print 42
age = 90
println(age) //Will Print 90
** the newAge constant cannot be reassigned to a new value. Trying to do so will give a compile time error**
//Constants
let newAge = 92 //Declaring a constant using let
println(newAge) //Will print 92.
“Use let to make a constant and var to make a variable”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l
var is variable which can been changed as many times you want and whenever
for example
var changeit:Int=1
changeit=2
//changeit has changed to 2
let is constant which cannot been changed
for example
let changeit:Int=1
changeit=2
//Error becuase constant cannot be changed
Even though you have already got many difference between let and var but one main difference is:
let is compiled fast in comparison to var.
var is the only way to create a variables in swift. var doesn't mean dynamic variable as in the case of interpreted languages like javascript. For example,
var name = "Bob"
In this case, the type of variable name is inferred that name is of type String, we can also create variables by explicitly defining type, for example
var age:Int = 20
Now if you assign a string to age, then the compiler gives the error.
let is used to declare constants. For example
let city = "Kathmandu"
Or we can also do,
let city:String = "Kathmandu"
If you try to change the value of city, it gives error at compile time.
let is used for constants that can’t be modified while var is an ordinary variable
Example:
let name = “Bob”
Something like name = “Jim” will throw an error since a constant can’t be modified.
SIMPLE DIFFERENCE
let = (can not be changed)
var = (any time update)
Source: https://thenucleargeeks.com/2019/04/10/swift-let-vs-var/
When you declare a variable with var, it means it can be updated, it is variable, it’s value can be modified.
When you declare a variable with let, it means it cannot be updated, it is non variable, it’s value cannot be modified.
var a = 1
print (a) // output 1
a = 2
print (a) // output 2
let b = 4
print (b) // output 4
b = 5 // error "Cannot assign to value: 'b' is a 'let' constant"
Let us understand above example: We have created a new variable “a” with “var keyword” and assigned the value “1”. When I print “a” I get output as 1. Then I assign 2 to “var a” i.e I’m modifying value of variable “a”. I can do it without getting compiler error because I declared it as var.
In the second scenario I created a new variable “b” with “let keyword” and assigned the value “4”. When I print “b” I got 4 as output. Then I try to assign 5 to “let b” i.e. I’m trying to modify the “let” variable and I get compile time error “Cannot assign to value: ‘b’ is a ‘let’ constant”.
The let keyword is used to declare a constant and the var keyword is used to declare a variable. Variables created with these either references, pointers or values.
Difference between them is that when you create a variable using let it will become constant upon declaration which can not modify or reassign later. In contrast, a varible with var can be assigned right away or later or noty at all. In swift, you have to be very explicit about what you are declaring.
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.