2. Constants, variables & types¶
What & why¶
Programs store values. Swift makes you decide up front whether a value can change: let declares a constant, var a variable. This one habit — preferring let — prevents a huge class of bugs.
let and var¶
let maxPlayers = 4 // constant: can never be reassigned
var score = 0 // variable: can change
score = 10
score += 5 // 15
// maxPlayers = 8 // ERROR: cannot assign to value: 'maxPlayers' is a 'let' constant
Rule of thumb: write let everywhere. Change it to var only when the compiler tells you that you reassign it.
A constant can be declared first and assigned once later:
let greeting: String
if score > 10 {
greeting = "High score!"
} else {
greeting = "Keep going"
}
print(greeting)
Types and type inference¶
Swift is statically typed: every value has a type known at compile time. You rarely have to write it, because the compiler infers it:
let age = 30 // Int
let pi = 3.14159 // Double
let name = "Ada" // String
let isReady = true // Bool
let initial: Character = "A" // must annotate: a plain "A" would infer String
Add a type annotation with : Type when inference can't pick what you want, or to be explicit:
let ratio: Double = 3 // 3.0 — the literal adapts to the annotation
let small: UInt8 = 200
var total: Int // declared, assigned later
Check a type with type(of:):
The core types¶
| Type | Holds | Example |
|---|---|---|
Int |
whole numbers (64-bit on modern platforms) | 42, -7, 1_000_000 |
Double |
64-bit floating point | 3.14, 2.5e3 |
Float |
32-bit floating point (rarely needed) | 1.5 |
Bool |
true / false |
true |
String |
text | "hello" |
Character |
a single user-perceived character | "a", "🙂" |
There are also sized integers — Int8, Int16, Int32, Int64, UInt8, … UInt64 — for binary formats and APIs that need exact sizes. Use plain Int for everyday counting and indexing, even for values that can't be negative.
Underscores make big literals readable:
No implicit conversions¶
Swift never silently converts between numeric types:
let items = 3
let price = 4.5
// let total = items * price // ERROR: binary operator '*' cannot be applied to 'Int' and 'Double'
let total = Double(items) * price // 13.5 — convert explicitly
Converting down truncates:
Converting from text can fail, so it returns an optional (see Optionals):
Tuples¶
A tuple groups a few values of possibly different types:
let point = (x: 3, y: 4)
print(point.x, point.y) // 3 4
let (w, h) = (1920, 1080) // decompose into two constants
let (status, _) = (404, "Not Found") // _ ignores a value
Tuples are great for quick, lightweight groupings (especially function results). For anything longer-lived, use a struct (Intermediate, lesson 1).
Naming¶
lowerCamelCasefor variables, constants, functions:userCount,fetchData()UpperCamelCasefor types:String,TaskItem- Names can contain almost any Unicode character, but be kind to your teammates.
- Reserved words (like
class,func,in) need backticks to be used as names — just pick another name.
typealias¶
Give an existing type a clearer name:
Common mistakes¶
- Using
varfor everything. The compiler even warns: "variable was never mutated; consider changing to 'let'". Listen to it. - Mixing
IntandDoublein arithmetic without converting. - Assuming
Int("12.5")works. It returnsnil—Intonly parses whole numbers. UseDouble("12.5"). - Using the wrong default for
Character.let c = "a"is aString. Annotate: Characterif you need one. - Using
UInt"because it can't be negative". Subtractions that go below zero crash at runtime. PreferInt.
Exercises¶
- Declare a constant for your birth year and a variable for the current year. Print your age.
- Declare
let a = 7andlet b = 2.0. Printa / b. (You'll need a conversion.) - Print
type(of:)for42,42.0,"42",true,(1, "a"), and[1, 2]. - Convert
"123","12.3", and"abc"toIntand print each result. What do you see, and why? - Create a tuple
person = (name: "Grace", age: 85), then decompose it into two separate constants. - Try to reassign a
let. Read the error, then fix it two ways (change tovar, or remove the reassignment).
Recap¶
letfor values that never change (default),varfor ones that do.- Types are inferred; annotate with
: Typewhen needed. Int,Double,Bool,String,Charactercover most everyday needs.- No implicit numeric conversion — use
Double(x),Int(x). - Tuples bundle a few values together.
Next: Numbers & math →