What is a variable? This is a place in the memory where we can store some data and use it later in our program. A good example is if you want to take an action based on a user's input, then the input should be stored somewhere on the device (computer). Usually, this place is in the device's memory. To let our program know that we need such a place, we have to express that. A var statement is used.
In Swift, declaring a variable looks like this:
var text = "Hello world!"
This code creates a place in the memory, called text, where we store the text, Hello world!. Later, we can use it to carry out some meaningful actions.
An advantage of a variable is that it can be changed later to contain a different value. Here, we should be careful—Swift is pretty strict about types (this will be discussed later), and, thus, we can't mix different value types. There are strict rules that should be followed, and we will get familiar with these soon. So, in our case, we can do the following to change the text that is stored in our variable, named text:
text = "Hey, It's Swift!"
Now we know what a variable is and how to work with variables. Let's try to do some calculations using variables, with stored integer values:
var five = 5
var four = 4
var sum = four + five
In the preceding code, we have created three variables. The first two were initialized with literal expressions, or simply with exact values. In the code, we can use complex calculations, and the Swift compiler will handle this case easily as follows:
var five = 2 + 3
This is the same as the previous code snippet.
The last variable sum is initialized with the value of the expression four + five. To calculate this expression, the compiler uses the values stored in the previously declared variables (on the previous lines). The evaluation happens once the code is executed. What does this mean: The evaluation happens once the code is executed? In short, if four or five contain different values, then the sum variable will reflect this. The code is working with the names of the places in memory, but the actual result depends on the values stored there.
We could read the preceding code like this:
-
Create a place in the memory, which we will call five, and store the value 5 in it
-
Create a place in the memory, which we will call four, and store the value 4 in it
-
Create another place in the memory, called sum, and store the value of the expression of what's stored in four plus what's stored in five
Usually, we use variables to allocate places in memory, which we will modify in the following code. But we don't always want to change the value of a variable once it is set. Thus, to simplify it, there is a special word in Swift, let, which denotes a place in the memory that won't be changed in the future. Its value is set initially and it can't be changed. (This is slightly different when we are working with objects, but this will become clear later in the book.)
The following code defines a place in memory that won't be updated. If we try to update it, then the Swift compiler will inform us that it is not possible. The value on the left is a constant and we are trying to change it:
let helloWorld = "Hello World!"
helloWorld = "Hello, Swift World!" //the compiler is complaining
The exact error is: Cannot assign to value: 'helloWorld' is a 'let' constant, which means that we are trying to set a new value to a constant.
Let's see how we can update our previous code snippets, once we know that there are var and let keywords.
The first code with the text variable should be the same, because we change the value of the variable text. The second code, with the sum of two integers, could be rewritten as follows:
let five = 5
let four = 4
let sum = four + five
A good practice is to keep using let whenever possible. The compiler gives us hints all the time. Of course, it's possible to keep something stored in a variable instead of a constant while developing, but if we want to squeeze out every single bit of performance, then we should stick to the best practice—replace all unmodified variables with constants.
Why do we gain performance when using let? The short answer is, the compiler knows that this place in the memory will be used only for reading from operations, and it cuts all the extra logic, which is needed to support modifications. The developers can reason locally and don't need to foresee any future changes of this value, because it is immutable.
Now we are familiar with variables, it's the perfect time to introduce the concept of a type. First, each variable has a type. The type defines the set of values which can be stored in a variable. Each type uses a different amount of the device's memory. Based on the type, the compiler knows how much space should be allocated when we declare a new variable.
In Swift, we define the type of a variable after the declaration of the variable itself. Our first code would look like this:
var text:String = "Hello World"
Is it mandatory to add a type declaration after each variable definition? No.
The Swift compiler is quite smart, and it infers the types based on the expressions on the right side. There are many examples which could illustrate how smart it is. But we should remember one: if the variable or constant is initialized, then we can simply omit the type. Of course, explicitly pointing to the type will make the code easier for other developers to understand. It's good to keep the same code style through all your code across every project. For some projects, it could be better if the type is omitted; for some, it may be worse.
Let's present all the basic types that Swift uses. The numbers are presented by several different types, based on the precision which is needed. The largest type takes extra memory, but it can store bigger values. The integer numbers can be stored in variables or constants from the following types: Int, Int8, Int16, Int32, Int64, UInt, UInt32, and UInt64. Floating-point numbers can be of the following types: Float, Float32, Float64, and Double. We are already familiar with the String type. It's used to store text in computer memory. Later, the text can be manipulated and presented to the user in different forms. The other quite popular data type is Bool, which takes exactly two values—true or false. We will discuss the need of boolean expressions later in this chapter, once we get familiar with conditional statements in Swift. We will define enumerable types and tuples. These are specific types that we can define, compared to the other ones, which are already defined for us.
Until now, we could declare variables or constants in one particular way. There are advanced ways to do this—one is to declare multiple variables on a single line, like this:
var a, b, sum: Double
All variables are from the same type, namely, Double.
We can specify a different type for each one, which gives us the freedom to declare variables/constants in a single shot on the same line.
The following code is an example of this:
var greeting: String, age:Int, money:Double
We can expand this even further by setting a default value, like in the following code:
var x:Double = 3.0, b:Bool = true
Of course, Swift is smart enough, so the following code has the very same meaning:
var x = 3.0, b = true
This automatic process is called type inference and greatly reduces the unnecessary boilerplate code which we would have to write.
Before diving into the details related to the different data types, we should know how to add comments to our code. Comments are blocks of text which are part of the source code, but they are removed when the source code is compiled.
The compilation is a complex process of transforming the code to machine code (in the case of Swift, it's something like this: S).
The comment's role is to clarify the code. There are two types of comments that we can use when we are developing a program in Swift. The first type is a single-row comment, which starts with // (double slash) and continues until the end of the row. Usually, developers prefer to start this comment on a new row or to add it to the end of a line, presenting a detail about the code, so it's easier for the reader to understand the encoded programming logic. The other type is a block comment, which starts with /* (slash and asterisk) and ends with */ (asterisk and slash). The comment can start anywhere, and continues until the matching ending sequence.
An interesting improvement from C++ or some other languages is that we can have several comment blocks which are nested in other comment blocks.
This is something new, which simplifies the process when we are adding comments.
When writing good code, try to add comments to make it easily understandable. In most cases, naming the variables with explicit names helps, but, usually, a brief comment is enough to clear the fog around a pretty complex sequence of your code.