Adding and subtracting one
Adding 1 to a variable is so common that many languages give it a dedicated operator, ++, and subtracting 1 gets --. Swift does not have either of them. Swift 3 removed them, and the idiomatic way to write the same thing is a compound assignment:
var number = 10
number += 1
print(number) // 11
number -= 1
print(number) // 10
number += 1 means "take the current value of number, add 1 and store the result back in number". -= does the same with subtraction. The variable has to be declared with var. A let constant can't change, so the compiler rejects the operator:
error: left side of mutating operator isn't mutable: 'number' is a 'let' constant
Writing number++ is rejected as well, with an error that points you to the replacement:
error: cannot find operator '++' in scope; did you mean '+= 1'?
Post-increment and pre-increment
In languages that have ++, the operator comes in two forms. The postfix form (x++) gives back the value from before the change. The prefix form (++x) gives back the value after it. This lesson reproduces both behaviours in Swift, and the trick is the order of two statements: read the value, and change it.
Post-increment: read first, then change
var count = 5
let before = count // read the old value
count += 1 // then change the variable
print(before) // 5
print(count) // 6
before is a separate constant. It received a copy of the number, so the later change to count doesn't touch it.
Pre-increment: change first, then read
var count = 5
count += 1
let after = count // read the new value
print(after) // 6
print(count) // 6
Both constants end up as snapshots of count taken at different moments. The same pattern works for decrement, with -= 1 in place of += 1.
Unlike ++ in other languages, += in Swift is a statement that changes the variable and produces no value you can use. You can't write let x = (count += 1) and expect the old or new number. That is why the pattern needs a separate line to capture the value.
The exercise, step by step
- Create a variable.
var number = 18. It must bevar, because every following step changes it. - Increment it.
number += 1takes it from 18 to 19. - Post-increment. Save the current value in a constant named
post, then increment.postkeeps 19 whilenumberbecomes 20. - Pre-increment. Increment first, then save the value in a constant named
pre. After step 3 incremented once, this step increments again, sonumberis 21 andpreholds the new value, 21. - Decrement.
number -= 1bringsnumberdown by one.
The solution in Swift
var number = 18
number += 1
let post = number
number += 1
number += 1
let pre = number
number -= 1
Tracing the values line by line:
| Line | number | Other values |
|---|---|---|
var number = 18 | 18 | |
number += 1 | 19 | |
let post = number | 19 | post is 19 |
number += 1 | 20 | |
number += 1 | 21 | |
let pre = number | 21 | pre is 21 |
number -= 1 | 20 |
At the end post is 19, pre is 21 and number is 20.
Common mistakes
- Using
letfor the counter. A constant can't be incremented. Usevarfor anything that changes. - Writing
number++or--number. They don't exist in Swift. Use+= 1and-= 1. - Capturing the value in the wrong place. If you move
let post = numberbelow the increment, it holds the new value, which makes it a pre-increment. The position of the capture line is the whole difference. - Using
postorpreas variables. They are constants, so a laterpost += 1is an error. They record a moment, and the changing value stays innumber. - Overflow.
Intis 64 bits in Swift. Adding 1 toInt.maxcrashes the program at run time instead of wrapping around.
Key takeaways
- Swift has no
++or--. Use+= 1and-= 1on avar. - "Post" means read, then change. "Pre" means change, then read.
- A
letconstant records a value at one moment and never follows later changes.
