Cheat sheet
Closure
How to spot a closure
If a function/method accepts a closure, the type annotation is (A...) -> B where:
(A...)is a set of parameter types. This could be:- a single parameter:
(Int) - multiple parameters separated by commas:
(String, String)
- a single parameter:
-> Bdenotes the return type.
For example, the Array.firstIndex(where:) method has the following signature:
func firstIndex(where predicate: (Self.Element) throws -> Bool) rethrows -> Self.Index?
In this method, the closure is predicate, broken up like this:
- A single parameter of the type
Self.Element(this represents whatever element the array contains; in an array ofInt,Self.Elementis equivalent toInt) throws, meaning that the predicate is allowed to throw an exception.- The method returns
Self.Index?, an optional type representing the index of the element, if it exists.
Map
map(_:) applies a transformation to a collection using a closure, resulting in a new collection. Use it to process some data without affecting the original collection.
Note: in Swift, it is generally preferable to use let constants rather than var variables.
let numbers = [1, 5, 10, 25]
// Long syntax.
let doubled = numbers.map({ number in
return number * 2
})
// Short syntax.
let doubled = numbers.map { $0 * 2 }
Filter
filter(_:) applies a filter to a collection using a closure, resulting in a new collection. The closure allows you to apply a Boolean expression to each element in the collection. Only if the closure returns true is the element included in the new collection.
let names = ["Alan", "James", "Ryan", "Sofia", "Benjy"]
// Long syntax.
let namesWithLetterS = names.filter({ name in
return name.lowercased().contains("s")
})
// Short syntax.
let namesWithLetterS = names.filter { $0.lowercased().contains("s") }
Reduce
OOP: structs
Creating objects (a.k.a. instances)
When you create an object, this is also called instantiation: the process of making instances of a struct.
struct Car {
let make: String
let model: String
let year: Int
}
// This is one instance.
let junkPile = Car(make: "Reliant", model: "Robin", year: 1980)
// These are multiple instances, generated at random.
let makes = ["Ford", "Holden", "Mazda"]
let models = ["Junkpile", "Scrapmetal", "Hunkajunk"]
let cars = (1990...1995).map {
Car(make: makes.random!, model: models.random!, year: $0)
}
Static properties
Properties marked with static belong to the struct, not to an instance. This is useful for data related to the struct that will never change. In your particular usage this year, think the kinds of constants you would make SCREAM_LIKE_THIS in Python!
struct Car {
let make: String
let model: String
let year: Int
// All cars go "beep". No exceptions.
static let hornSound: String = "Beep!"
/// Makes the horn go beep.
func makeHornSound() {
// This is an entirely pointless function, but hey…
print(Car.hornSound)
}
}
let junkPile = Car(make: "Reliant", model: "Robin", year: 1980)
junkPile.makeHornSound() // Beep!
Static methods
Much like properties, methods can also be made static. They are called on the struct, not on an object/instance.
struct Car {
let make: String
let model: String
let year: Int
static let makes: [String] = ["Ford", "Holden", "Mazda"]
static models: [String] = ["Junkpile", "Scrapmetal", "Hunkajunk"]
/// A static method to create a random pile of crap.
///
/// Returns: a utter mess of a car.
static func rustPile() -> Car {
return Car(
make: Car.makes.randomElement()!,
model: Car.models.randomElement()!,
year: (1980...1990).randomElement()!
)
}
}
let terribleMotor = Car.rustPile()