Values and types
Holding numbers and text in named values, choosing between let and var, and how whole numbers and decimals behave.
A name for a value
A value you want to reuse gets a name. let rooms = 4 puts the number four under the name rooms, and from then on you can read it or use it in a sum.
Give the value a type when the meaning is not obvious. var price: Double = 12 says the name holds a decimal number, and the compiler uses that to keep you honest.
let stays, var may change
let fixes a value once and refuses to let it change. var allows a new value later. Reaching for let first is a good habit, because a value that never changes is one fewer thing to track.
When you try to change a let, the compiler stops you at that line rather than letting the mistake travel quietly through the rest of the program.
A value that cannot change needs no tracking across the lines below it, and the compiler refuses an accidental write at the exact line where it happens. If most of your let names become var, the program is probably doing too much in one place.
Whole numbers, decimals and truth
An Int is a whole number and can be negative. A Double is a number with a decimal point. A Bool is either true or false, and a String is text. Most of the time Swift works out the type from the value you write.
Two whole numbers divide to a whole number, so 3 / 2 is 1 and % gives the remainder. Mixing an Int with a Double needs a conversion such as Double(3), because Swift will not silently change one into the other.
Division deserves a worked example. 7 / 2 is 3 and 7 % 2 is 1, so the two answers add back to seven. With a negative number the quotient moves toward zero, so -7 / 2 is -3, and the remainder keeps the sign of the dividend, so -7 % 2 is -1. Converting either side with Double(...) changes the answer, so convert before dividing, not after.
When the compiler needs to be told
Swift works out a type from the value on the right, so let rooms = 4 is an Int without you writing the word. Inference stops at the literal: a sum of two Int values stays an Int, even when the answer you have in mind has a fraction in it.
Write the type when the value alone is ambiguous or when the name should hold a decimal from the start. let price: Double = 12 is accepted because the literal can be read as a decimal, while let price: Double = count is refused because that would quietly change an Int into a different representation.
Inference stops at the literal because a literal has no type until something gives it one. 12 can be an Int or a Double, and the annotation decides. A named value is different: count already has a type, and writing Double beside it would ask the compiler to change that type silently. The conversion Double(count) is the explicit way to ask.
Where the numbers are stored
An Int on a modern Apple platform is 64 bits wide, which is enough for about nine quintillion values in either direction. That sounds unlimited until a loop multiplies without a bound. Swift checks the result and stops the program on overflow rather than wrapping around to a negative number, so a wrong total is loud instead of quiet.
A Double stores its value in binary, and most decimal fractions have no exact binary form. 0.1 is the usual example: the stored value is very close to one tenth but not exactly it, so 0.1 + 0.2 prints 0.30000000000000004. For prices and measurements, work in whole pence or grams and convert only for display.
Names, types and arithmetic
let rooms = 4
var guests = 3
guests = guests + 2
print(rooms * guests)
let price: Double = 12.5
let rate = 0.1
print(price * rate)
print(3 / 2) // whole division
print(3 % 2) // the remainder
let ready: Bool = true
print(ready)Three mistakes follow from the same rule. 7 / 2 is 3, because two Int values divide to an Int and the fraction is dropped. Adding an Int to a Double is refused until you convert one side with Double(...). And a let is fixed for good, so a second assignment is an error rather than an update.
A small bill
Run it and check each printed line. Then change the price and the tax rate, and predict the new total before you run it again.
Try these next
- Work out
7 / 2,7 % 2and7.0 / 2.0by hand, then print all three and compare. - Store a whole number in an
Int, convert it withDouble(...), and divide it by three. - Give a value an explicit type annotation, then assign a value of another type and read the compiler message.
A temperature, two ways
Run it and compare the two averages. Then change both readings so the sum is even, and predict whether the two averages still differ.
A type is a promise about what a value can hold. If you promise a Double and hand over a plain whole number, Swift may refuse rather than guess, so write 12.0 when the decimal matters.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
What happens when you try to give a new value to a let?
