0
1
00:00:00,600 --> 00:00:01,150
Hey, guys.
1

2
00:00:01,170 --> 00:00:04,790
Welcome to another Swift Deep Dive. In this Deep Dive,
2

3
00:00:04,800 --> 00:00:07,020
we're going to talk about Closures.
3

4
00:00:07,020 --> 00:00:13,440
Closures are essentially anonymous functions or functions without a name and they're essentially a self-contained
4

5
00:00:13,440 --> 00:00:17,420
package of functionality that we can pass around and use.
5

6
00:00:17,430 --> 00:00:22,320
So we've seen a lot of functions up till now. And we know that when we create a function, we always start
6

7
00:00:22,440 --> 00:00:24,240
with the func keyword.
7

8
00:00:24,240 --> 00:00:30,180
And then we give our function a name, and then we have a section that's enclosed in parentheses that
8

9
00:00:30,180 --> 00:00:34,710
represent the input parameters and the input parameter type.
9

10
00:00:34,740 --> 00:00:41,160
And finally, we have this little dash and angle bracket to represent the returnType, i.e., what is the
10

11
00:00:41,160 --> 00:00:45,440
data type of the thing that we will output from our function.
11

12
00:00:45,630 --> 00:00:52,110
And in the body of our function, i.e., between the curly braces, we get our function to do something, and
12

13
00:00:52,110 --> 00:00:59,100
then finally, if our function has an output, then we get it to return the output.
13

14
00:00:59,100 --> 00:01:02,540
So, essentially, our function is a little bit like a bread cutting machine.
14

15
00:01:02,610 --> 00:01:08,520
You have an input, say, your bread, and then you pass it through your function and you get an output.
15

16
00:01:08,520 --> 00:01:11,610
Something happens to the bread, it gets cut up in slices.
16

17
00:01:11,610 --> 00:01:17,550
You can determine how thick or thin the slice is. But, essentially, all it is is a bunch of functionality
17

18
00:01:17,820 --> 00:01:23,940
that's packaged together and given a function name so that we can refer to it later on when we need
18

19
00:01:23,940 --> 00:01:31,530
that functionality, so we can call the method or call the function by its name, giving it inputs and receiving
19

20
00:01:31,530 --> 00:01:32,840
the outputs.
20

21
00:01:32,880 --> 00:01:37,320
So up till now, we've seen three variations on function.
21

22
00:01:37,320 --> 00:01:43,850
We've seen functions that only do something without needing an input or having an output.
22

23
00:01:43,950 --> 00:01:49,950
And then we've seen functions which take an input and then we've seen functions which do all three, i.e.,
23

24
00:01:49,970 --> 00:01:54,650
a function that takes input and has an output and does something in between.
24

25
00:01:55,050 --> 00:01:58,110
But let's now look at the step beyond that.
25

26
00:01:58,140 --> 00:02:06,360
The interesting thing about functions is that you can actually pass a function as an input to another
26

27
00:02:06,360 --> 00:02:13,170
function and you can also have a function as the output of another function.
27

28
00:02:13,440 --> 00:02:16,110
So I can show you this better in playgrounds.
28

29
00:02:16,110 --> 00:02:18,900
So I've got a blank playground here.
29

30
00:02:18,900 --> 00:02:24,630
What I'm going to do is I'm going to create a function that's called calculator, and what it does is
30

31
00:02:24,750 --> 00:02:33,570
it takes a number n1, and it also takes another number n2, and they're both integers, and the calculator
31

32
00:02:33,690 --> 00:02:36,080
also returns an integer.
32

33
00:02:36,150 --> 00:02:44,580
So all that our calculator is going to do right now is it's just going to add n1 to n2, and it returns
33

34
00:02:44,610 --> 00:02:48,690
the result of the first number added to the second number.
34

35
00:02:48,960 --> 00:02:57,420
So let's give it a spin. Let's say a calculator and give it to numbers 2 and 3. And we can see the output
35

36
00:02:57,600 --> 00:02:58,980
is 5.
36

37
00:02:58,980 --> 00:03:02,150
So all is working as expected.
37

38
00:03:02,160 --> 00:03:10,110
Now, say, if we wanted to change the calculator to a multiplication calculator, then we would have to go
38

39
00:03:10,110 --> 00:03:14,040
into the body of the calculator and change the return statement.
39

40
00:03:14,040 --> 00:03:23,760
Now, what if we wanted to be able to pass in a function as an input to our calculator function in order
40

41
00:03:23,760 --> 00:03:28,050
to determine what sort of mathematical operation it should perform?
41

42
00:03:28,050 --> 00:03:33,780
So in order to do this, we're going to create another function, and I'm going to call my function add,
42

43
00:03:34,350 --> 00:03:36,390
and it, again, takes two numbers.
43

44
00:03:36,420 --> 00:03:41,320
So let's call it no1 and no2,
44

45
00:03:41,370 --> 00:03:45,990
and it returns a number as well.
45

46
00:03:45,990 --> 00:03:54,380
So now we're going to return no1 + no2.
46

47
00:03:54,380 --> 00:04:01,490
So this is our basic addition operand, essentially, and we're going to go and modify our calculator
47

48
00:04:01,520 --> 00:04:08,900
so that it not only takes two numbers as inputs, but we're gonna give it a third input in the form of
48

49
00:04:08,930 --> 00:04:15,980
a function. In order to put this function in as an input, we're going to have to boil down this function
49

50
00:04:16,070 --> 00:04:17,680
into its data types.
50

51
00:04:17,810 --> 00:04:24,320
So if we have a look at this function, you can see that it takes two inputs, both in the form of integers
51

52
00:04:24,500 --> 00:04:27,410
and returns an integer as an output.
52

53
00:04:27,440 --> 00:04:37,230
So if you boil down this function to its data types, essentially, all it is is int, int, and returns an int.
53

54
00:04:37,250 --> 00:04:47,180
So if we take this representation of that function and we pass it in as the data type of our third parameter
54

55
00:04:47,240 --> 00:04:50,510
which we'll call operation,
55

56
00:04:50,510 --> 00:04:57,170
so as you can see, we've got three parameters as inputs for our calculator function, n1, n2, so those
56

57
00:04:57,170 --> 00:05:00,090
are the two numbers that we're going to give our calculator.
57

58
00:05:00,200 --> 00:05:08,990
And then, finally, we've got a parameter called operation and the data type of operation is in the format
58

59
00:05:09,140 --> 00:05:16,130
of a function, i.e., it's not just int, it's not just string, but it's actually the boiled down version
59

60
00:05:16,220 --> 00:05:23,080
of a function, i.e., two integer parameter inputs and returns a single integer.
60

61
00:05:23,090 --> 00:05:29,210
Now, the next thing to do is to change this return statement. At the moment, our calculator is still returning
61

62
00:05:29,510 --> 00:05:31,940
the first number multiplied it by the second number.
62

63
00:05:31,940 --> 00:05:40,160
But instead, what we want to do is we want to call this function that's currently called operation,
63

64
00:05:40,250 --> 00:05:45,770
so we can, instead, return operation and we can give it the required inputs.
64

65
00:05:45,770 --> 00:05:52,470
So as we specified, it takes two inputs and returns one output, and the two inputs have to be integers.
65

66
00:05:52,520 --> 00:05:57,730
So this is where we're going to pass in our n1 and n2.
66

67
00:05:57,900 --> 00:06:04,700
So now, Xcode is complaining over here because this is no longer how you call the calculator function
67

68
00:06:05,060 --> 00:06:08,550
because instead of having two parameters, it's now got three.
68

69
00:06:08,630 --> 00:06:13,830
So let's try calling it again and get Xcode to type out the function for us.
69

70
00:06:13,850 --> 00:06:22,400
So the first number is, again, two, second number is three, and the operation is going to be "add," so that we
70

71
00:06:22,400 --> 00:06:27,680
pass in this function as an input parameter.
71

72
00:06:27,680 --> 00:06:34,080
And, essentially, what happens is that two goes over here, three goes into here,
72

73
00:06:34,160 --> 00:06:41,300
and the operation, this function add gets passed in over here as the operation.
73

74
00:06:41,300 --> 00:06:49,640
And what we return from our calculator function is we return by calling this function that's under the
74

75
00:06:49,640 --> 00:06:55,370
operation parameter passing in the original inputs n1, n2.
75

76
00:06:55,490 --> 00:07:02,200
So whichever function gets passed in as the operation will process these two numbers.
76

77
00:07:02,210 --> 00:07:11,540
So in this case, we passed in the add a function as the operation, and the n1, n2 then goes over
77

78
00:07:11,540 --> 00:07:15,820
here as the inputs, and we return n2 + n2.
78

79
00:07:15,860 --> 00:07:23,350
So if I create another function, say, let's call it multiply, then I can have again two inputs.
79

80
00:07:23,360 --> 00:07:25,030
So no1,
80

81
00:07:25,040 --> 00:07:26,340
no2.
81

82
00:07:27,260 --> 00:07:31,110
And it also returns an integer.
82

83
00:07:31,220 --> 00:07:37,010
So in this case, we're returning no1 multiplied by no2.
83

84
00:07:37,010 --> 00:07:45,320
So if I go ahead and change the function that we pass in to our calculator by changing it to multiply
84

85
00:07:45,320 --> 00:07:53,030
instead, then you can see that the result changes to 6, because now instead of this add function being
85

86
00:07:53,030 --> 00:07:58,980
passed in as the operation, we've actually got the multiply function being passed in here.
86

87
00:07:59,390 --> 00:08:07,220
So I hope you'll believe me now when I tell you that you can pass in functions as inputs into other
87

88
00:08:07,220 --> 00:08:12,980
functions and you can also use functions as the return type.
88

89
00:08:12,980 --> 00:08:17,870
So now let's clean this up a little bit because we've actually got quite a few lines of code to do something
89

90
00:08:17,870 --> 00:08:19,150
quite simple.
90

91
00:08:19,310 --> 00:08:26,270
So to make things clear, I've got a multiply function that gets passed into the calculator as an input
91

92
00:08:26,690 --> 00:08:30,890
and it's used to perform the calculation.
92

93
00:08:30,890 --> 00:08:35,800
So at the moment, everything's very wordy and we've got quite a few lines of code.
93

94
00:08:35,840 --> 00:08:41,270
Now, if I wanted to cut this down, I can instead use a closure.
94

95
00:08:41,390 --> 00:08:48,500
So closures if you remember are anonymous functions or you can consider functions as named closures.
95

96
00:08:48,770 --> 00:08:54,110
But, essentially, they're just packages of functionality which you can pass around freely.
96

97
00:08:54,180 --> 00:08:59,580
So if we have a look at the structure of our function, which we're very familiar with, we've got a section
97

98
00:08:59,610 --> 00:09:00,870
that's the input.
98

99
00:09:00,870 --> 00:09:03,590
Remember, that's the part between the parentheses,
99

100
00:09:03,840 --> 00:09:05,630
and then we've got a part that's the output.
100

101
00:09:05,640 --> 00:09:09,090
So that's the part that comes after the dash and angle bracket.
101

102
00:09:09,360 --> 00:09:15,260
And then we've got this func keyword which we've been using every single time we created a new function.
102

103
00:09:15,300 --> 00:09:19,400
And finally, we've got a part that represents the name of the function.
103

104
00:09:19,410 --> 00:09:26,460
So in order to convert this function to a closure, all we need to do is to remove the keyword func and
104

105
00:09:26,460 --> 00:09:28,100
the name of the function.
105

106
00:09:28,320 --> 00:09:36,120
And then we move this open bracket from the end of the line to the beginning of the closure and we replace
106

107
00:09:36,120 --> 00:09:39,620
it instead with the keyword "in."
107

108
00:09:39,630 --> 00:09:45,680
So now we've successfully converted a function into a closure.
108

109
00:09:45,810 --> 00:09:48,720
And as you can see, it's pretty anonymous.
109

110
00:09:48,780 --> 00:09:56,580
All you have is a block of code which you can pass around freely into other functions or set as a variable.
110

111
00:09:57,210 --> 00:10:04,370
So let's try and do the same with our multiply function. Instead of calling this multiply function,
111

112
00:10:04,380 --> 00:10:10,950
what we can do instead is we can pass in a closure. So remember the first thing we do is we delete the
112

113
00:10:10,950 --> 00:10:14,440
func keyword and the name of the function.
113

114
00:10:14,550 --> 00:10:21,810
The next thing we do is we move this open bracket to the beginning of the block of code and we replace
114

115
00:10:21,810 --> 00:10:23,930
it with the keyword "in."
115

116
00:10:24,690 --> 00:10:32,250
So now we have our closure and we can put it in here as an input parameter.
116

117
00:10:32,250 --> 00:10:39,450
So you'll notice that nothing has changed, output wise, it's still working as it did before, but we've
117

118
00:10:39,450 --> 00:10:46,410
now cut down on two lines of code. But it gets crazier than that. We can actually cut down this code even
118

119
00:10:46,410 --> 00:10:47,190
further.
119

120
00:10:47,220 --> 00:10:53,030
So as you know Swift has the ability to infer data types based on the value.
120

121
00:10:53,040 --> 00:11:00,660
So if you have a variable "a" that contains a number, then Swift will automatically assign the data type
121

122
00:11:00,990 --> 00:11:07,280
int to this variable, and that's called type inference. And we can use that here as well.
122

123
00:11:07,290 --> 00:11:12,520
So instead of explicitly declaring the data type of these parameters, we can actually delete it
123

124
00:11:12,660 --> 00:11:19,680
and it still works fine. Because when we pass in these inputs into this closure, the compiler will be
124

125
00:11:19,680 --> 00:11:23,820
able to figure out what the data type of these parameters should be.
125

126
00:11:23,940 --> 00:11:27,390
And you can do the same thing with the return type.
126

127
00:11:27,390 --> 00:11:33,150
So you can actually get rid of this part entirely because we have a calculation in here, i.e., the first
127

128
00:11:33,150 --> 00:11:38,630
number multiplied by the second number, the output has a data type based on the inputs.
128

129
00:11:38,820 --> 00:11:46,850
So we can actually get rid of this part, too, and get the compiler to infer the data type of the output.
129

130
00:11:46,860 --> 00:11:52,840
Now, our code is beginning to look a lot shorter than it did before. And I'm not even done yet.
130

131
00:11:52,860 --> 00:11:59,940
We can also get rid of this return keyword because we're inside a closure and there is a operation that's
131

132
00:11:59,940 --> 00:12:01,020
being carried out.
132

133
00:12:01,080 --> 00:12:07,680
The compiler can infer that you want something to be returned based on the simple fact that you're processing
133

134
00:12:07,680 --> 00:12:10,980
something inside your closure.
134

135
00:12:10,980 --> 00:12:14,880
So we're pretty much at the point where everything can be expressed in one line.
135

136
00:12:14,880 --> 00:12:21,420
Now, you might think that it can't get any shorter, but it can. Because in Swift, closures has the ability
136

137
00:12:21,420 --> 00:12:25,130
to provide anonymous parameter names.
137

138
00:12:25,140 --> 00:12:30,180
So here we've given our parameters names: no1 and no2.
138

139
00:12:30,240 --> 00:12:34,700
And later, we refer to those parameter names to carry out our expression.
139

140
00:12:34,800 --> 00:12:40,230
But instead of doing this, you can actually use the anonymous parameter names.
140

141
00:12:40,320 --> 00:12:49,920
So in Swift, a dollar sign with a zero refers to the first parameter, and a dollar sign with a 1 refers
141

142
00:12:49,920 --> 00:12:52,770
to the second parameter, and so on and so forth.
142

143
00:12:52,800 --> 00:13:02,280
So instead of expressing this line like so, we can actually just change it to first parameter multiplied
143

144
00:13:02,400 --> 00:13:04,750
by second parameter.
144

145
00:13:05,190 --> 00:13:14,430
So now if I assign the result of this calculator function to a constant and then I print out this result,
145

146
00:13:14,850 --> 00:13:21,450
you can see that we've still got the same result as before even though we've cut down four lines of
146

147
00:13:21,450 --> 00:13:24,840
code, everything is still working exactly the same.
147

148
00:13:24,840 --> 00:13:31,110
And to take this to the extreme, we can actually cut down this line even further, believe it or not, because
148

149
00:13:31,110 --> 00:13:39,630
in Swift there is a rule whereby if the last parameter in your function is a closure, i.e., everything
149

150
00:13:39,630 --> 00:13:42,890
between the open and closing curly braces.
150

151
00:13:42,900 --> 00:13:49,950
That's what our closure has simplified down to. Then you can actually omit the last parameter name and
151

152
00:13:49,950 --> 00:13:56,010
you can close the input section, and simply just have the closure trailing at the end.
152

153
00:13:56,010 --> 00:13:58,750
So this is called a trailing closure.
153

154
00:13:58,830 --> 00:14:03,420
So, again, as you can see, that has done nothing to change our result.
154

155
00:14:03,420 --> 00:14:06,260
Everything is still working as it did before.
155

156
00:14:06,540 --> 00:14:12,700
But instead of all of this, we now just have a single line.
156

157
00:14:12,780 --> 00:14:19,170
So one of the nice things about closures is that they can dramatically simplify your code and cut down
157

158
00:14:19,170 --> 00:14:20,200
on your code.
158

159
00:14:20,310 --> 00:14:27,180
But the downside to that is that readability suffers, because for somebody who is not very familiar with
159

160
00:14:27,180 --> 00:14:34,380
Swift coming in and looking at this line of code, it can be quite confusing. Because as you remember, we
160

161
00:14:34,380 --> 00:14:42,180
went through many many steps in order to cut down all of this expressive syntax into something that
161

162
00:14:42,180 --> 00:14:43,850
is very, very succinct.
162

163
00:14:43,860 --> 00:14:50,340
Now, you can argue that shorter is better, or some programmers might argue that this has way more style
163

164
00:14:50,700 --> 00:14:57,240
then something like this, which is true, but you always have to strike the balance between simplicity
164

165
00:14:57,390 --> 00:14:58,770
and readability.
165

166
00:14:58,770 --> 00:15:03,720
So that decision is mostly up to you. If you become more and more familiar with the language, you might
166

167
00:15:03,780 --> 00:15:09,070
actually have a preference of having a vastly simplified code file.
167

168
00:15:09,090 --> 00:15:15,780
Now, of course, this is just a made-up example to show you the process of passing in functions as inputs
168

169
00:15:15,840 --> 00:15:18,540
or passing in functions as outputs.
169

170
00:15:18,540 --> 00:15:24,810
This code doesn't stand up in real life because it's so much easier to simply just write "n1 * n2
170

171
00:15:24,900 --> 00:15:26,860
equals the result,"
171

172
00:15:26,910 --> 00:15:27,600
right?
172

173
00:15:27,630 --> 00:15:31,050
So let me show you how we would use this in real life.
173

174
00:15:31,050 --> 00:15:36,990
Now, say, if we have an array with a bunch of numbers and we want to be able to add 1 to each of the
174

175
00:15:36,990 --> 00:15:38,570
items in the array.
175

176
00:15:38,610 --> 00:15:44,070
Now, the roundabout way of doing this is using what's called a for-loop and you can iterate through each
176

177
00:15:44,070 --> 00:15:47,410
of these items in order to add 1 to every one of them.
177

178
00:15:47,460 --> 00:15:53,690
But there's a much simpler way of doing this because there is a function called map that Swift provides
178

179
00:15:53,700 --> 00:15:58,410
that allows you to transform every single item in a collection type.
179

180
00:15:58,410 --> 00:16:04,190
So collection types are arrays or dictionaries, basically, collections of items.
180

181
00:16:04,200 --> 00:16:06,050
So let me show you how it would work.
181

182
00:16:06,060 --> 00:16:09,740
We first have to define a rule in order to transform our array.
182

183
00:16:09,780 --> 00:16:19,020
So if I create a function code addOne and all it does is it takes one number and it returns a number,
183

184
00:16:19,050 --> 00:16:21,210
but, of course, with 1 added to it.
184

185
00:16:21,300 --> 00:16:25,910
So, essentially, we return n1 + 1.
185

186
00:16:25,950 --> 00:16:27,500
So that's pretty simple, right?
186

187
00:16:27,750 --> 00:16:34,830
But then what we can do is we can tap into our array and we can use the map function to transform this
187

188
00:16:34,830 --> 00:16:35,740
array.
188

189
00:16:35,790 --> 00:16:41,310
Now, the map function takes an input in the form of another function.
189

190
00:16:41,340 --> 00:16:49,380
So if we use addOne here and you go ahead and hit enter, you can see that your array gets transformed
190

191
00:16:49,740 --> 00:16:54,290
with every single item being one greater than previously.
191

192
00:16:54,300 --> 00:16:55,770
So that's pretty neat.
192

193
00:16:55,770 --> 00:17:03,150
But why do we have to write so much code when we know all about closures? And I'd like to pose this as
193

194
00:17:03,150 --> 00:17:03,790
a challenge to you.
194

195
00:17:03,800 --> 00:17:10,560
Can you write the code to turn this into a closure instead? Pause the video, check the closure syntax,
195

196
00:17:10,680 --> 00:17:14,840
and I'll show you the solution in a bit. Ready?
196

197
00:17:14,840 --> 00:17:16,460
Here's the solution.
197

198
00:17:16,610 --> 00:17:21,890
So if you remember, in order to turn this into a closure, we delete the func keyword and would delete
198

199
00:17:21,920 --> 00:17:24,000
the name of the function.
199

200
00:17:24,110 --> 00:17:32,600
Then we move the open curly brace to the beginning of the code block and we replace that instead with
200

201
00:17:32,600 --> 00:17:34,400
the keyword "in."
201

202
00:17:34,430 --> 00:17:39,700
So now we can put this, instead of using that function name.
202

203
00:17:39,860 --> 00:17:44,660
And, of course, we can use some of those snazzy tricks that we learned about previously where we first
203

204
00:17:44,660 --> 00:17:52,130
used type inference to make the compiler infer the data type of the input as well as the output. We can
204

205
00:17:52,130 --> 00:17:52,490
use
205

206
00:17:52,550 --> 00:18:00,470
an implicit return, because we only have one expression inside our closure, so we can get rid of the return
206

207
00:18:00,470 --> 00:18:01,610
keyword.
207

208
00:18:01,700 --> 00:18:10,220
And finally, we can get rid of this whole thing by just simply using the shorthand notation for the parameters
208

209
00:18:10,280 --> 00:18:16,430
and we say the first parameter plus 1. And we can go even further and get rid of these parentheses
209

210
00:18:16,730 --> 00:18:25,580
because our closure is the last item in the list of parameters, i.e,. it's trailing. And if we print the
210

211
00:18:25,610 --> 00:18:33,890
result of this out, you can see that we've mapped our previous array to increase each item by 1. So Swift
211

212
00:18:33,890 --> 00:18:39,440
has three of these really useful high-level functions called map, reduce, and filter. And you can do some
212

213
00:18:39,440 --> 00:18:41,250
really useful things with them.
213

214
00:18:41,300 --> 00:18:47,420
For example, you've realized that your array contains integers, right? But we actually want to convert each
214

215
00:18:47,420 --> 00:18:49,610
of them into strings.
215

216
00:18:49,610 --> 00:18:57,410
So what you can do instead is this. Let's say, we create a new constant code newArray and we set it to
216

217
00:18:57,410 --> 00:19:07,340
equal array.map, and we use the string interpolation method where we enclose the integer inside
217

218
00:19:07,400 --> 00:19:08,200
a string.
218

219
00:19:08,210 --> 00:19:17,360
So now if we print out this newArray, you can see that it's composed of entirely strings. So we've essentially
219

220
00:19:17,360 --> 00:19:27,050
stringified each item in this array by simply writing a very short bit of code and using the map functionality.
220

221
00:19:27,050 --> 00:19:33,530
So in essence, you'll find that closures can be a very succinct way of expressing your code. And in the
221

222
00:19:33,530 --> 00:19:40,670
cases where you're passing in functions into other functions, it can make your code a lot more readable.
222

223
00:19:40,670 --> 00:19:46,640
Now, of course, that depends on your own familiarity with the syntax and other people's familiarity
223

224
00:19:46,640 --> 00:19:53,120
if you're working on a project together. But all in all, closures allow you to package anonymous blocks
224

225
00:19:53,240 --> 00:19:57,410
of functionality and pass it around in your code.
225

226
00:19:57,500 --> 00:20:00,950
So essentially, this is the syntax for a closure.
226

227
00:20:01,100 --> 00:20:05,410
You have the parentheses that surround the input parameters.
227

228
00:20:05,600 --> 00:20:12,560
You have the dash and angle brackets that specify the return type, and the "in" keyword denotes the beginning
228

229
00:20:12,740 --> 00:20:14,120
of your closure body.
229

230
00:20:14,210 --> 00:20:20,780
So this is the functionality that your closure is going to perform and everything is contained inside
230

231
00:20:20,840 --> 00:20:27,500
these curly braces. And the closure doesn't have a name or a funky word and you can recognize it by this
231

232
00:20:27,620 --> 00:20:35,030
syntax. If you'd like to know more about closures or review what we've discussed in this lesson, I recommend
232

233
00:20:35,030 --> 00:20:39,080
having a quick look at this section in the Swift Language Guide.
233

234
00:20:39,110 --> 00:20:43,760
As always, you'll find the link on the course resources page, and I'll see you on the next lesson.
