Vocabulary for this course

The terms the chapters assume, in plain words. You can open this from any chapter.

array
An ordered list of values of one type, reached by position starting at zero.
block
A group of lines of code that run together, often inside curly brackets.
closure
A piece of code you can store in a value and pass to other code, remembered with the names around it.
compiler
The program that turns the code you write into something the machine can run, reporting mistakes before it does.
dictionary
A collection of key and value pairs, where each key appears once and finds its value.
enum
A type whose value is one of a fixed set of named cases, which may each carry extra data.
expression
A piece of code that produces a value, such as a sum or a call to a function.
function
A named piece of code that takes values and returns a result when called.
guard
A check that must pass before the code after it runs, leaving the scope early when it fails.
method
A function that belongs to a type and is called on a value of that type.
nil
The absence of a value, allowed only where a type says a value may be missing.
operator
A symbol such as plus or equals that combines values into a new one.
optional
A type that either holds a value or holds nothing, written with a question mark after the type.
optional chaining
Writing a question mark before something you reach into, so the result is nil when the value is missing.
property
A named value that belongs to a type or to one of its values.
protocol
A list of requirements that a type promises to meet, so code can work with any type that meets them.
scope
The region of code where a name can be used before it goes out of reach.
string interpolation
Putting a value inside text with a backslash and parentheses, so the value becomes part of the text.
struct
A type that groups related values and makes a copy whenever it is given another name or passed along.
subscript
A way to read or write an item in an array or dictionary by putting a key or position in square brackets.
type
What kind of value something is, such as a whole number or text, and what it can do.
unwrap
To get the value out of an optional after checking that something is there.

Swift from the ground up

Values and types

Holding numbers and text in named values, choosing between let and var, and how whole numbers and decimals behave.

Part 2 of 12

Beginner14 min readBack to Courses

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.

Output
Click "Run" to execute your code

Try these next

  • Work out 7 / 2, 7 % 2 and 7.0 / 2.0 by hand, then print all three and compare.
  • Store a whole number in an Int, convert it with Double(...), 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.

Output
Click "Run" to execute your code

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?