**Swift Programming from Scratch**

The book is **updated for Swift 3** and the Swift Sandbox is integrated, making the exercises interactive. Read more about the book here.

?You can buy **Training app** + the **PDF** and **ePub** versions of the book!

**Chapter 9: Closures**

Closures are self contained chunks of code that can be passed around and used in your code. Closures can capture and store references to any constants or variables from the context in which they are defined. This is know as closing over those variables, hence the name closures. Closures are use intensively in the Cocoa frameworks – which are used to develop iOS or Mac applications.

Functions are a special kind of closures. There are three kinds of closures:

*global functions*– they have a name and cannot capture any values*nested functions*– they have a name and can capture values from their enclosing functions*closure expressions*– they don’t have a name and can capture values from their context

The thing to keep in mind for the moment is that you already have an intuition about closures. They are almost the same as functions but don’t necessarily have a name.

```
// a closure that has no parameters and return a String
var hello: () -> (String) = {
return "Hello!"
}
hello() // Hello!
// a closure that take one Int and return an Int
var double: (Int) -> (Int) = { x in
return 2 * x
}
double(2) // 4
// you can pass closures in your code, for example to other variables
var alsoDouble = double
alsoDouble(3) // 6
```

Remember the array `sort`

method? There is similar one named `sort(by:)`

that takes a closure as an parameter:

```
var numbers = [1, 4, 2, 5, 8, 3]
numbers.sort(by: <) // this will sort the array in ascending order
numbers.sort(by: >) // this will sort the array in descending order
```

The `<`

and `>`

operators are defined as functions, which can be referenced as closures. Here is an example for calling `sort`

that uses a closure:

```
var numbers = [1, 4, 2, 5, 8, 3]
numbers.sort(by: { x, y in
return x < y
})
print(numbers)
// [1, 2, 3, 4, 5, 8]
```

**Declaring a closure**

The general syntax for declaring closures is:

{ (`parameters`

) -> `return type`

**in**

`statements`

}

If the closure does not return any value you can omit the arrow (`->`

) and the return type. This also applies to the case where the type of the closure can be infered.

{ (`parameters`

) **in**

`statements`

}

Closures can use inout parameters, but cannot assign default values to any parameter. Also closure parameters cannot have external names.

Let’s look at some examples:

```
var noParameterAndNoReturnValue: () -> () = {
print("Hello!")
}
var noParameterAndReturnValue: () -> (Int) = {
return 1000
}
var oneParameterAndReturnValue: (Int) -> (Int) = { x in
return x % 10
}
var multipleParametersAndReturnValue: (String, String) -> (String) =
{ (first, second) -> String in
return first + " " + second
}
```

The examples from above don’t declare the type of each parameter, if you do so you don’t need to state the return type of the closure because it can be inferred.

```
var noParameterAndNoReturnValue = {
print("Hello!")
}
var noParameterAndReturnValue = { () -> Int in
return 1000
}
var oneParameterAndReturnValue = { (x: Int) -> Int in
return x % 10
}
var multipleParametersAndReturnValue =
{ (first: String, second: String) -> String in
return first + " " + second
}
```

**Shorthand Parameter Names**

Swift provides shorthand parameter names for closures. You can refer to the parameters as `$0`

, `$1`

, `$2`

and so on. To use shorthand parameter names ignore the first part of the declaration.

```
numbers.sort({ return $0 < $1 })
var double: (Int) -> (Int) = {
return $0 * 2
}
var sum: (Int, Int) -> (Int) = {
return $1 + $2
}
```

**Capturing Values**

In the beginning of the chapter I mentioned that closures can capture values. Let’s see what that means:

```
var number = 0
var addOne = {
number += 1
}
var printNumber = {
print(number)
}
printNumber() // 0
addOne() // number is 1
printNumber() // 1
addOne() // number is 2
addOne() // number is 3
addOne() // number is 4
printNumber() // 4
```

So a closure can remember the reference of a variable or constant from its context and use it when it’s called. In the example above the `number`

variable is in the global context so it would have been destroyed only when the program would stop executing. Let’s look at another example, in which a closure captures a variable that is not in the global context:

```
func makeIterator(from start: Int, step: Int) -> () -> Int {
var i = start
return {
let currentValue = i
i += step
return currentValue
}
}
var iterator = makeIterator(from: 1, step: 1)
iterator() // 1
iterator() // 2
iterator() // 3
var anotherIterator = makeIterator(from: 1, step: 3)
anotherIterator() // 1
anotherIterator() // 4
anotherIterator() // 7
anotherIterator() // 10
```

**Trailing Closure Syntax**

If the last parameter of a function is a closure, you can write it after the function call.

```
numbers.sort { $0 < $1 }
func sum(from: Int, to: Int, f: (Int) -> (Int)) -> Int {
var sum = 0
for i in from...to {
sum += f(i)
}
return sum
}
sum(from: 1, to: 10) {
$0
} // the sum of the first 10 numbers
sum(from: 1, to: 10) {
$0 * $0
} // the sum of the first 10 squares
```

**Closures are reference types**

Closures are reference types. This means that when you assign a closure to more than one variable they will refer to the same closure. This is different from value type which make a copy when you assign them to another variable or constant.

```
// a closure that take one Int and return an Int
var double: (Int) -> (Int) = { x in
return 2 * x
}
double(2) // 4
// you can pass closures in your code, for example to other variables
var alsoDouble = double
alsoDouble(3) // 6
```

**Implicit Return Values**

Closures that have only one statement will return the result of that statement. To do that simply omit the `return`

keyword.

`array.sort { $0 < $1 }`

**Higher order functions**

A higher order function is a function that does at least one of the following:

- takes a function as input
- outputs a function

Swift has three important higher order functions implemented for arrays: map, filter and reduce.

**Map**

Map transforms an array using a function.

```
[ x1, x2, ... , xn].map(f) -> [f(x1), f(x2), ... , f(xn)]
```

Let’s take as an example the problem of converting an array of numbers to an array of strings.

```
[1, 2, 3] -> ["1", "2", "3"]
```

One way of solving this problem would be to create an empty array of strings, iterate over the original array transforming each element and adding it to the new one.

```
var numbers = [1, 2, 3]
var strings: [String] = []
for number in numbers {
strings.append("\(number)")
}
```

The other way of solving this problem is by using map:

```
var numbers = [1, 2, 3]
var strings = numbers.map { "\($0)" }
```

`{ "\($0)" }`

is the closure we provided to solve this problem. It takes one parameter and converts it into a string using string interpolation.

The closure that we need to give to map take one parameter and will be called once for each of the elements from the array.

**Filter**

Filter selects the elements of an array which satisfy a certain condition.

For example let’s remove all the odd numbers from an array:

```
var numbers = [1, 2, 3, 4, 5, 6, 7, 8]
var evenNumbers = numbers.filter { $0 % 2 == 0 }
// evenNumbers = [2, 4, 6, 8]
```

Or remove all the even numbers:

```
var oddNumbers = numbers.filter { $0 % 2 == 1 }
// oddNumbers = [1, 3, 5, 7]
```

The closure that we need to give to map takes one parameter and will be called once for each of the elements from the array. It should return a `Bool`

value, if it’s `true`

the element will be copied into the new array otherwise no.

**Reduce**

Reduce combines all the values from an array into a single value.

For example we can reduce an array of numbers to their sum.

```
var numbers = [1, 2, 3, 4, 5]
var sum = numbers.reduce(0) { $0 + $1 } // 15
```

Reduce take two parameters, an initial value and a closure that will be used to combine the elements of the array. The closure provided to reduce takes two parameters, the first one is the partial result and the second one will be an element from the array. The closure will be called for each element once. In the sum example we started the sum from 0 and the closure added the partial sum with each element.

Here is another cool way in which we can use the fact that Swift operators are implemented as functions:

```
var numbers = [1, 2, 3, 4, 5]
var sum = numbers.reduce(0, +) // 15
```

**9.1 K Times**

Write a function named `applyKTimes`

that takes an integer `K`

and a `closure`

and calls the closure `K`

times. The closure will not take any parameters and will not have a return value.

`func applyKTimes(_ K: Int, _ closure: () -> ())`

Function call:

```
applyKTimes(3) {
print("We Heart Swift")
}
```

Output:

```
We Heart Swift
We Heart Swift
We Heart Swift
```

Function call:

```
applyKTimes(2) {
print("Tic")
print("Tac")
}
```

Output:

```
Tic
Tac
Tic
Tac
```

Remember that you can call a closure just like a regular function.

```
func applyKTimes(_ K: Int, _ closure: () -> ()) {
for _ in 1...K {
closure()
}
}
```

**9.2 Div3**

Use `filter`

to create an array called `multiples`

that contains all the multiples of 3 from `numbers`

and then print it.

Input:

`var numbers = [1, 2, 3, 4, 6, 8, 9, 3, 12, 11]`

Expected values:

`multiples = [3, 6, 9, 3, 12]`

Input:

`var numbers = [3, 3, 27, 3, 99]`

Expected values:

`multiples = [3, 3, 27, 3, 99]`

Input:

`var numbers = [2, 4, 8, 16, 32, 128, 1]`

Expected values:

`multiples = []`

Think of the condition the numbers have to satisfy so that they’re divisible by`3`

.

```
let numbers = [1, 2, 3, 4, 6, 8, 9, 3, 12, 11]
let multiples = numbers.filter { $0 % 3 == 0 }
print(multiples)
```

**9.3 Max**

Find the largest number from `numbers`

and then print it. Use `reduce`

to solve this exercise.

Input:

`var numbers = [4, 7, 1, 9, 6, 5, 6, 9]`

Output:

```
9
```

What would be the initial value for our reduce function?

How can you “combine” 2 numbers to get the maximum between them?

```
let numbers = [4, 7, 1, 9, 6, 5, 6, 9]
let max = numbers.reduce(numbers[0]) {
if $0 > $1 {
return $0
} else {
return $1
}
}
print(max) // 9
```

**9.4 Join**

Join all the strings from `strings`

into one using `reduce`

. Add spaces in between strings. Print your result.

Input:

`var strings = ["We", "Heart", "Swift"]`

Output:

```
"We Heart Swift"
```

Input:

`var strings = ["lonely"]`

Output:

```
"lonely"
```

What would be the initial value for our reduce function?

How can you combine the strings so that they have spaces between them?

```
let strings = ["We", "Heart", "Swift"]
let string = strings.reduce("") {
if $0 == "" {
return $1
} else {
return $0 + " " + $1
}
}
print(string)
```

**9.5 Sorting**

Sort `numbers`

in ascending order by the number of divisors. If two numbers have the same number of divisors the order in which they appear in the sorted array does not matter.

Input:

`var numbers = [1, 2, 3, 4, 5, 6]`

Expected values:

```
numbers = [1, 2, 3, 5, 4, 6]
// 1 has one divisor
// 2, 3 and 5 have 2
// 4 has 3 divisors
// 6 has 4 divisors
// [1, 5, 2, 3, 4, 6] would also have been a valid solution
```

You’ll have to pass a closure that tells you how the numbers should be compared.

```
var numbers = [1, 2, 3, 4, 5, 6]
numbers.sort(by: { x, y in
func countDivisors(_ number: Int) -> Int {
var count = 0
for i in 1...number {
if number % i == 0 {
count += 1
}
}
return count
}
return countDivisors(x) < countDivisors(y)
})
```

**9.6 Chains**

Find the sum of the squares of all the odd numbers from `numbers`

and then print it. Use `map`

, `filter`

and `reduce`

to solve this problem.

Input:

`var numbers = [1, 2, 3, 4, 5, 6]`

Output:

```
25 // 1 + 9 + 25 -> 25
```

Input:

`var numbers = [2, 4, 6]`

Output:

```
0 // none of the numbers are odd
```

The order in which you apply the `map`

, `filter`

and `reduce`

operations is important.

```
var numbers = [1, 2, 3, 4, 5, 6]
let sum = numbers.filter {
$0 % 2 == 1 //select all the odd numbers
}.map {
$0 * $0 // square them
}.reduce(0, +) // get their sum
print(sum)
```

**9.7 For each**

Implement a function `forEach(array: [Int], _ closure: Int -> ())`

that takes an array of integers and a closure and runs the closure for each element of the array.

```
var array = [1,2,3,4]
forEach(array) {
print($0 + 1)
}
// This will be printed:
// 2
// 3
// 4
// 5
```

`func forEach(_ array: [Int], _ closure: (Int) -> ())`

Function input:

```
forEach([1, 2, 3, 4]) {
print($0 + 1)
}
```

Output:

```
2
3
4
5
```

Function input:

```
forEach([1, 2, 3, 4]) {
print($0 * $0)
}
```

Output:

```
1
4
9
16
```

```
func forEach(_ array: [Int], _ closure: (Int) -> ()) {
for number in array {
closure(number)
}
}
```

**9.8 Combine arrays**

Implement a function `combineArrays`

that takes 2 arrays and a closure that combines 2 Ints into a single Int. The function combines the two arrays into a single array using the provided closure.

Assume that the 2 arrays have equal length.

```
func combineArrays(_ array1: [Int],
_ array2: [Int],
_ closure: (Int,Int) -> Int) -> [Int]
```

Function input:

```
var array1 = [1,2,3,4]
var array2 = [5,5,5,3]
combineArrays(array1,array2) {
$0 * $1
}
```

Function output:

`[5,10,15,12]`

Function input:

```
var array1 = [5,14,77,12]
var array2 = [1,5,3,13]
combineArrays(array1,array2) {
return max($0,$1)
}
```

Function output:

`[5,14,77,13]`

You’ll have to iterate both arrays at the same time using an index.

```
func combineArrays(_ array1: [Int],
_ array2: [Int],
_ closure: (Int,Int) -> Int) -> [Int] {
var result: [Int] = []
for i in 0..<array1.count {
result.append(closure(array1[i],array2[i]))
}
return result
}
```

**Swift Programming from Scratch**

Read more about the book here.

?You can buy **Training app** + the **PDF** and **ePub** versions of the book!

Feel free to ask any questions in the comments bellow.

Fun!

Here’s my solution to 9.5:

“`var numbers = [1, 2, 3, 4, 5, 6]

numbers.sort({ x, y in

func factors(n: Int) -> [Int] {

return filter(1…n) { n % $0 == 0 }

}

return factors(x).count < factors(y).count

})“`

var sum: (Int, Int) -> (Int) = {

return $1 + $2

}

in xcode 7 beta 6 seeing this error:

Tuple types ‘(Int, Int’ and ‘(_,_,_)’ have a different number of elements (2 vs 3)

{ return $0 + $1 } wont give you that error. $0 is the first unnamed parameter. read the part title “Shorthand Parameter Names” from this chapter

To find the largest Int in an array try this instead.

let result = numbers.reduce(0){ max($0, $1) }

max is already a closure that takes two ints ->

`let result = numbers.reduce(0, combine: max)`

9.7 I used reduce

func forEach(array: [Int], withClosure closure: Int -> ()){

array.reduce(array[0], combine: {

closure($1)

return $1

})

}

Ever since learning ObjC & Swift, I had problem with blocks and closures.

Not anymore. This was pure gold!