Swift: When Should I Use "Var" Instead of "Let"

Swift: when should I use var instead of let ?

Use let whenever you can. Use var when you must. Making things immutable makes a lot of bugs impossible, so it should be your default choice. As much as possible, set all your values in init and never change them. Similarly, you should use struct when you can, and class when you must (though in my experience this is harder to achieve than using let).

So in your example, if you cannot set A.a during initialization, then yes, it should be var. But there is no need in your example to use var for B.b. (And there's no reason in either example to use class, at least in the way you've presented the question.)

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

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.

Using var vs. let in Swift 2 for maps

In this case the choice between var and let is more a matter of readability.

When people reading your code see var they expect that the value of that variable will change at some point. Analogously when they see let they know the variable can't change.

This separation is strong in the mind of swift programmers. Using var in a variable that is not meant to change can be misleading. Your program works just fine but it imposes a certain confusion to a reader, which is why you get a warning.

I tend to define local variables with let initially and later on change to var if needed.

var vs let in Swift

Rather than constant and variable, the correct terminology in swift is immutable and mutable.

You use let when you know that once you assign a value to a variable, it doesn't change - i.e. it is immutable. If you declare the id of a table view cell, most likely it won't change during its lifetime, so by declaring it as immutable there's no risk that you can mistakenly change it - the compiler will inform you about that.

Typical use cases:

  • A constant (the timeout of a timer, or the width of a fixed sized label, the max number of login attempts, etc.). In this scenario the constant is a replacement for the literal value spread over the code (think of #define)
  • the return value of a function used as input for another function
  • the intermediate result of an expression, to be used as input for another expression
  • a container for an unwrapped value in optional binding
  • the data returned by a REST API call, deserialized from JSON into a struct, which must be stored in a database

and a lot more. Every time I write var, I ask myself: can this variable change?. If the answer is no, I replace var with let. Sometimes I also use a more protective approach: I declare everything as immutable, then the compiler will let me know when I try to modify one of them, and for each case I can proceed accordingly.

Some considerations:

For reference types (classes), immutable means that once you assign an instance to the immutable variable, you cannot assign another instance to the same variable.

For value types (numbers, strings, arrays, dictionaries, structs, enums) immutable means that that once you assign a value, you cannot change the value itself. For simple data types (Int, Float, String) it means you cannot assign another value of the same type. For composite data types (structs, arrays, dictionaries) it means you cannot assign a new value (such as a new instance of a struct) and you cannot change any of their stored properties.

Also an immutable variable has a semantic meaning for the developer and whoever reading the code - it clearly states that the variable won't change.

Last, but maybe less important from a pure development point of view, immutables can be subject to optimizations by the compiler.

Whether to use var or let during instances creation in Swift?

Use let if:

  • it is a constant (or in the case of reference types like class, if the reference cannot be replaced with another reference); and
  • you're able to set it during the initialization process.

But if you need to be able to change it at a later point, use var, such as true variables whose values are not constant (or in the case of reference types, if you need to replace it with another instance). But variables and properties whose values are not set during the initialization process, you have to use var. For example, lazy stored properties use var because their value is not set when the initialization process completes, but only when you first reference it. Another example includes view controllers' references to their outlets that are hooked up only when the view hierarchy is created at a later point.

Needless to say, computed properties use var, too.

But, if you can use let, you should do so, as it's easier to write safe code if you know what is a constant and what is a variable. In your example, you'd use let.

Note: In the case of reference types, like class types, let does not mean that that the object itself is necessarily immutable, merely that you cannot replace it with another instance. If you want to enjoy control over whether it's immutable or not, consider using a value type (e.g. a struct).


Let me see if I can make that final note more clear. Consider:

class Foo {
var value: String
init(value: String) {
self.value = value
}
}

Then the following is permitted:

let obj = Foo(value: "a")
obj.value = "b" // changing mutable property of reference type, Foo, is permitted

But the following is not:

let obj = Foo(value: "a")
obj = Foo(value: "b") // replacing `obj` with a new instance of `Foo`, is not

If you don't want to be able to change value property, you can define value to be immutable (or at least, not publicly mutable), e.g.:

class Foo {
let value: String // or `private(set) var value: String`
init(value: String) {
self.value = value
}
}

Or don't define Foo as class (a reference type) and instead define it to be a struct (a value type):

struct Foo {
var value: String
init(value: String) {
self.value = value
}
}

let obj = Foo(value: "a")
obj.value = "b" // this is not permitted, because Foo value-type, `obj`, was declared with `let`, making it immutable

Note, that final example, declaring Foo as a value type (a struct) does change it fairly fundamentally, e.g.

var obj1 = Foo(value: "a")
var obj2 = obj1 // this value is a copy of `obj1` not a reference to the same object that `obj1` pointed to
obj1.value = "b"
print("\(obj1.value)") // will print "b"
print("\(obj2.value)") // will print "a"

But value types, while it requires a slightly different mindset to use them, are incredibly useful for easily writing safe code. See WWDC 2015 Building Better Apps with Value Types in Swift.

Why is let used instead of var in Swift?

As a matter of fact, as a Swift programmer, the question to ask is why not use var over let? This is one area where Swift differs greatly in semantics from other languages such as C#.

The reason is because once you obtain a reference to a table cell, that reference is not going to change for the lifetime of each invocation of this method. There are no reassignments to cell, because there is simply no reason to do so. And therefore there is no reason to make cell a variable.

In general, in Swift, you should default to using let, and only use var if you need to reassign. Remember that let only prevents the constant itself from being reassigned; you can still mutate the object that is being referenced, as is being done in cell.textLabel!.text = person... in this case.

There are other, subtle differences that are further covered in Apple's documentation, but this applies to the majority of cases.

What is the different between `if var` and `if let` in swift?

If you use the let then you will not be able to change myValue.

if let myValue = myObject.value as NSString? {
myValue = "Something else" // <-- Compiler error
}

On the other hand with var you can.

if var myValue = myObject.value as NSString? {
myValue = "Something else" // <-- It's fine
}

Please note that myValue does exists only within the scope of the if and changing its value does not produce effect outside of its scope.

Hope this helps.

Should I use var or let for an object later mutated?

The compiler is actually really good at determining whether you should use let or var, and in this case, it is correct.

var should be used anywhere the data will be mutated. For example:

  • A struct value where the properties will be mutated
  • Pointers (like your COpaquePointer)
  • Instances of classes that will be reassigned to different class instances

let should be used anywhere the data will not be mutated. For example:

  • Constants
  • Values to be added to arrays, dictionaries, arguments to functions, etc.
  • Class instances where the instance will not be reassigned.

Note that for instances of classes, you can still modify the properties of the class even if it is defined as let. var should only be used in this case when the class itself will be reassigned.

In the case of your newProfile variable, during it's lifetime it is never mutated. The object is created, then immediately appended to your array. That array needs to be defined with var because it is mutated with that append, but newProfile never gets changed. You can change the value that was appended from newProfile through the array at a later date if you'd like because the patientProfiles array is mutable.

A good practice for when you are not sure whether to use let or var is to start with let and see if the compiler complains. If it does, then change it to var.

Shouln't this be a var instead of let?

The variable is created and destroyed each time, so either would work just fine. It would be a different story if you had defined coordinatePoint above the for loop. In this case, you would have to use var.



Related Topics



Leave a reply



Submit