4

I'm new to Swift programming, and I've met the var and let types. I know that let is a constant and I know what that means, but I never used a constant mainly because I didn't need to. So why should I use var instead of let, at what situation should I use it?

Eilon
  • 87
  • 1
  • 5
  • you should use let whenever possible as the compiler is able to optimize better. – Daniel Bo Sep 22 '14 at 15:26
  • Constants are for ease of reading and helping the compiler optimize (both for the same reason: it's easier to reason about a variable that can never change its value. it makes the possible code branches a lot smaller). However, I would not use constants everywhere just because of compiler optimizations. Premature optimization etc etc... I would use it for your own readability whenever a variable never needs to change its value. And sometimes, you can slightly rewrite your code to where you only have to assign to a variable once so you can make it a let (but not if it's less readable then!) – Millie Smith Sep 22 '14 at 15:28
  • @AlexK. this question is more about the design principles. the one you linked is more about semantics. – Millie Smith Sep 22 '14 at 15:33

3 Answers3

20

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.

Antonio
  • 71,651
  • 11
  • 148
  • 165
5

Generally speaking, mutable state is to avoid as much as possible.

Immutable values help in reasoning about code, because you can easily track them down and clearly identify the value from the start to the end.

Mutable variables, on the other hand, make difficult to follow your data flow, since anyone can modify them at any time. Especially when dealing with concurrent applications, reasoning about mutable state can quickly become an incredibly hard task.

So, as a design principle, try to use let whenever possible and if you need to modify an object, simply produce a new instance.

Whenever you need to use a var, perhaps because using it makes the code clearer, try to limit their scope as much as possible and not to expose any mutable state. As an example, if you declare a var inside a function, it's safe to do so as long as you don't expose that mutability to the caller, i.e. from the caller point of view, it must not matter whether you used a var or a val in the implementation.

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • I'd upvote this answer, as I think it's far better than the other two (OP obviously understands the semantics, and you touched on readibility). However, I don't think it should be used everywhere. If one tries to write as much immutable code as possible, it can make the function long, ugly, and cumbersome. Sometimes vars make the code a lot cleaner. They should be used on a case by case basis. – Millie Smith Sep 22 '14 at 15:43
  • @MillieSmith, I see your point. Mutability should be an exception, in my opinion. Nevertheless, a little var in the code doesn't kill anyone, as long as the mutable state is not exposed. I'll update my answer. – Gabriele Petronella Sep 22 '14 at 15:51
0

In general, if you know a variable's value is not going to change, declare it as a constant. Immutable variables will make your code more readable as you know for sure a particular variable is never being changed. This might also be better for the compiler as it can take advantage of the fact that a variable is constant and perform some optimisations.

This doesn't only apply to Swift. Even in C when the value of a variable is not be changed after being initialised, it's good practise to make sure it's const.

So, the way you think about "I didn't need to" should change. You don't need a constant only for values like TIMEOUT etc. You should have a constant variable anywhere you know the value of a variable doesn't need to be changed after initialisation.

Note: This is more of a general "programming as a whole" answer and not specific to Swift. @Antonio's answer has more of a focus on Swift.

s16h
  • 4,647
  • 1
  • 21
  • 33