Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:00,000 --> 00:00:07,480
So now that we're comfortable calling built-in Ruby methods, the take blocks, we're ready
2
00:00:07,480 --> 00:00:09,720
to write our own methods that take blocks.
3
00:00:09,720 --> 00:00:12,560
Yeah, and this can really take you Ruby game up a level.
4
00:00:12,560 --> 00:00:16,160
We're going to start with a simple example in this module, but then we'll incrementally
5
00:00:16,160 --> 00:00:20,760
work up to more realistic use cases in the coming modules.
6
00:00:20,760 --> 00:00:24,240
So let's say we have this block attached to the times method here.
7
00:00:24,240 --> 00:00:28,720
And obviously when we run this, it's going to print out three times running the block.
8
00:00:28,720 --> 00:00:32,119
It's going to be very nice to realize that we've already seen how this works.
9
00:00:32,119 --> 00:00:33,839
But now we want to change things around a little bit.
10
00:00:33,839 --> 00:00:38,379
Instead of calling the times method, we want to associate a block with our own method,
11
00:00:38,379 --> 00:00:40,000
a method that we're going to define.
12
00:00:40,000 --> 00:00:46,239
And we're going to call that method run my block just to keep it really simple for now.
13
00:00:46,239 --> 00:00:50,120
When that method runs, we want it to call the block just once.
14
00:00:50,120 --> 00:00:52,440
So let's go ahead and define the method.
15
00:00:52,440 --> 00:00:59,239
We can be called run my block. And I'm going to start off just to print out there says
16
00:00:59,239 --> 00:01:01,040
starting method.
17
00:01:01,040 --> 00:01:05,039
And then it's going to end by saying back in method.
18
00:01:05,039 --> 00:01:08,320
But between these two lines, we actually want it to call the block.
19
00:01:08,320 --> 00:01:12,120
And the way we do that is by using yield.
20
00:01:12,120 --> 00:01:17,840
If we run this, we see starting in method running block and then back in method.
21
00:01:17,840 --> 00:01:22,400
So what happened is when the method was run here, it printed out starting in method.
22
00:01:22,400 --> 00:01:27,840
Then when yield was called, it passed control over to the block, which was here.
23
00:01:27,840 --> 00:01:29,840
And then it printed out running block.
24
00:01:29,840 --> 00:01:34,320
Then when the block was done, control ended up back on the next line,
25
00:01:34,320 --> 00:01:36,880
which printed out back in method.
26
00:01:36,880 --> 00:01:39,520
We can actually use this method to call any block.
27
00:01:39,520 --> 00:01:41,280
So we could change what the method does.
28
00:01:41,280 --> 00:01:44,880
Like perhaps the method says the time is now whatever.
29
00:01:44,880 --> 00:01:46,560
Sure, it doesn't matter what the block does.
30
00:01:46,560 --> 00:01:47,920
The time is now.
31
00:01:47,920 --> 00:01:51,360
And then Ruby will get the current time time about now.
32
00:01:51,360 --> 00:01:52,360
Right?
33
00:01:52,360 --> 00:01:54,120
Our run my block method doesn't care what the block does.
34
00:01:54,120 --> 00:01:55,360
It just yields to it.
35
00:01:55,360 --> 00:01:58,120
So inside the block, we can have any Ruby code we want.
36
00:01:58,120 --> 00:02:02,160
And every time we run that, it just prints out the current time.
37
00:02:02,160 --> 00:02:07,680
Now that calls the block once, but we saw how three dot times actually call the block multiple times.
38
00:02:07,680 --> 00:02:08,919
Three times in that case.
39
00:02:08,919 --> 00:02:10,680
So how does that work?
40
00:02:10,680 --> 00:02:12,520
So let's start over with the new method.
41
00:02:12,520 --> 00:02:14,560
Let's write a method that rolls the dice.
42
00:02:14,560 --> 00:02:17,240
Sure, let me just zap this out of here.
43
00:02:17,240 --> 00:02:18,760
We want a method called roll.
44
00:02:18,760 --> 00:02:22,679
So it's going to roll the dice and then it's going to yield control over to our block.
45
00:02:22,679 --> 00:02:25,480
Inside of the block, we're going to generate a random number.
46
00:02:25,480 --> 00:02:29,760
Ruby, we can do that using the ran method and then just pass it a range of numbers.
47
00:02:29,760 --> 00:02:31,320
1 to 6.
48
00:02:31,320 --> 00:02:34,519
And then let's print out you rolled whatever number.
49
00:02:34,519 --> 00:02:35,519
Okay.
50
00:02:35,519 --> 00:02:38,959
Now, to make that work, we need to define the roll method.
51
00:02:38,959 --> 00:02:39,959
All right.
52
00:02:39,959 --> 00:02:40,959
Roll.
53
00:02:40,959 --> 00:02:41,959
What's it going to do?
54
00:02:41,959 --> 00:02:45,120
Well, I'm going to go ahead and say starting method just so we see that.
55
00:02:45,120 --> 00:02:48,680
And I'm going to say back in method.
56
00:02:48,680 --> 00:02:50,000
What's this we have before?
57
00:02:50,000 --> 00:02:52,800
And then between those two lines, we need to call the block.
58
00:02:52,800 --> 00:02:55,440
We know to do that calling yield.
59
00:02:55,440 --> 00:02:57,160
We can actually call a yield multiple times.
60
00:02:57,160 --> 00:02:59,200
Every time we call a yield, it's going to call the block.
61
00:02:59,200 --> 00:03:01,320
So we want to roll the dice three times.
62
00:03:01,320 --> 00:03:03,800
We would call yield three times.
63
00:03:03,800 --> 00:03:08,640
If we go ahead and run that, we see we get U rolled A and a random number each time.
64
00:03:08,640 --> 00:03:12,800
And it called that block three times just as we expected.
65
00:03:12,800 --> 00:03:14,120
What an animation help?
66
00:03:14,120 --> 00:03:15,880
Why have one for you?
67
00:03:15,880 --> 00:03:20,079
Here's a roll method that yields to the block twice and how we called the method with
68
00:03:20,079 --> 00:03:21,079
the block.
69
00:03:21,079 --> 00:03:25,400
When the method is called, the first line runs and prints starting method.
70
00:03:25,400 --> 00:03:29,200
The second line then runs which yields control to the block.
71
00:03:29,200 --> 00:03:33,800
Effectively, whenever yield is called, the method stops what it's doing and lets the
72
00:03:33,800 --> 00:03:35,400
block do its thing.
73
00:03:35,400 --> 00:03:39,079
In this case, the block generates a random number and prints it out.
74
00:03:39,079 --> 00:03:43,280
Once the block is done executing, control returns back to the method.
75
00:03:43,280 --> 00:03:48,440
So the third line of our method runs and we yield once again to the block, the block runs
76
00:03:48,440 --> 00:03:51,040
and prints out a second random number.
77
00:03:51,040 --> 00:03:53,080
We then return back to the method.
78
00:03:53,080 --> 00:03:56,600
The method prints out back in method and we're done.
79
00:03:56,600 --> 00:04:01,640
Notice here the method runs once and the block runs twice.
80
00:04:01,640 --> 00:04:05,040
You can call yield as many times as you want to inside the method.
81
00:04:05,040 --> 00:04:08,640
In fact, that's exactly what iterator methods do.
82
00:04:08,640 --> 00:04:13,200
Now, it's important to keep in mind that the block isn't a method parameter.
83
00:04:13,200 --> 00:04:17,200
We don't see a parameter called something like the block right here.
84
00:04:17,200 --> 00:04:19,479
There's no name for the block at all.
85
00:04:19,479 --> 00:04:23,760
There's nothing in the method signature that says it even expects a block.
86
00:04:23,760 --> 00:04:26,080
It's just a regular method definition.
87
00:04:26,080 --> 00:04:30,520
Every method accepts a block and there's nothing special we have to do to accept that
88
00:04:30,520 --> 00:04:31,520
block.
89
00:04:31,520 --> 00:04:35,880
But we do have to call yield to actually run the block.
90
00:04:35,880 --> 00:04:37,840
So let's see what happens if we don't call yield.
91
00:04:37,840 --> 00:04:41,840
I'm just going to go back down to one yield call right here and I'm going to comment
92
00:04:41,840 --> 00:04:42,840
it out.
93
00:04:42,840 --> 00:04:45,159
And try to run the code.
94
00:04:45,159 --> 00:04:48,799
Well, it expected the block we didn't get in the error, but you notice it just printed
95
00:04:48,799 --> 00:04:51,599
out starting method back in method.
96
00:04:51,599 --> 00:04:56,120
So it basically just ignored the block that was attached to the method.
97
00:04:56,120 --> 00:05:01,120
So now it happens if we do yield to the block, but we don't have a block associated
98
00:05:01,120 --> 00:05:02,120
to that method.
99
00:05:02,120 --> 00:05:03,799
So I'm just going to comment out the block right there.
100
00:05:03,799 --> 00:05:09,200
We're calling roll without a block, but we're yielding inside that method.
101
00:05:09,200 --> 00:05:14,200
So now if we run it, we get an error. It says no block was given.
102
00:05:14,200 --> 00:05:16,680
We get this local jump error.
103
00:05:16,680 --> 00:05:21,280
So whenever you call yield, it's expecting a block to be attached to it and then call.
104
00:05:21,280 --> 00:05:23,960
If you don't have a block, you're going to get an error.
105
00:05:23,960 --> 00:05:28,400
So if yield is called, there must be an associated block.
106
00:05:28,400 --> 00:05:34,039
So what if we want the method to work if a block is passed and if the method doesn't
107
00:05:34,039 --> 00:05:35,760
get passed a block?
108
00:05:35,760 --> 00:05:38,840
We're going to call yield, we only want to call it if a block was attached.
109
00:05:38,840 --> 00:05:44,080
We can check for it by saying if and then using the method block underscore given question
110
00:05:44,080 --> 00:05:48,120
mark that returns true if there's an associated block and false otherwise.
111
00:05:48,120 --> 00:05:50,840
So if there's not a block, this line of code won't be run at all.
112
00:05:50,840 --> 00:05:51,840
There's a block.
113
00:05:51,840 --> 00:05:52,840
It will yield to it.
114
00:05:52,840 --> 00:05:54,760
Okay, so we've got roll set up.
115
00:05:54,760 --> 00:05:56,560
There's no associated block there.
116
00:05:56,560 --> 00:05:59,200
If we run it now, we shouldn't get an error and we don't.
117
00:05:59,200 --> 00:06:02,320
It just doesn't do anything between starting method and back in method.
118
00:06:02,320 --> 00:06:07,680
And if we go back to attaching our block here, pull that back up in line and we run it,
119
00:06:07,680 --> 00:06:10,800
well now yield to the block because a block is given.
120
00:06:10,800 --> 00:06:15,040
So we saw how blocks can take parameters when we were using the built in Ruby methods.
121
00:06:15,040 --> 00:06:17,320
Well, we can do the same thing with our methods.
122
00:06:17,320 --> 00:06:22,200
Yeah, for example, the times and the up to method in particular, we saw that it passed
123
00:06:22,200 --> 00:06:24,080
the number to the block.
124
00:06:24,080 --> 00:06:29,200
So let's rearrange our method so it passes a parameter to a associated block.
125
00:06:29,200 --> 00:06:32,920
So let's have the method pass in the name of the person rolling the dice.
126
00:06:32,920 --> 00:06:37,240
Okay, well, we know that block parameters go inside the block after do here and they go inside
127
00:06:37,240 --> 00:06:38,640
of vertical bars.
128
00:06:38,640 --> 00:06:42,840
So the name of this parameter is going to be called, well, it's actually called name.
129
00:06:42,840 --> 00:06:46,440
And then we can print out name of whoever rolled a number.
130
00:06:46,440 --> 00:06:49,200
Okay, we'll just change that over to name there.
131
00:06:49,200 --> 00:06:54,960
Okay, so we need to supply a value to name when this block is invoked or when it's run.
132
00:06:54,960 --> 00:06:56,640
We do that inside of our roll method.
133
00:06:56,640 --> 00:07:00,280
I'm going to go ahead and drop off this if block given because I think you know how that works.
134
00:07:00,280 --> 00:07:06,800
I'm going to drop this down to just yield and then to supply a name, we actually pass it as a parameter to yield.
135
00:07:06,800 --> 00:07:08,400
Now you can use parentheses here if you want.
136
00:07:08,400 --> 00:07:16,039
For example, we could pass in Larry, but the parentheses are optional so we can just drop those and just say yield this string Larry.
137
00:07:16,039 --> 00:07:23,039
So whatever we supply here is a parameter to yield will get substituted in as the value of that block parameter.
138
00:07:23,039 --> 00:07:26,400
So if we run this now, Larry rolled a five.
139
00:07:26,400 --> 00:07:29,599
What if we also want to pass in the random number?
140
00:07:29,599 --> 00:07:31,880
Yeah, we can actually pass that as a block parameter as well.
141
00:07:31,880 --> 00:07:35,760
Let's say our roll method is going to generate the random number.
142
00:07:35,760 --> 00:07:37,880
So we'll put that up here inside a roll.
143
00:07:37,880 --> 00:07:40,200
That's not the responsibility of the block anymore.
144
00:07:40,200 --> 00:07:45,400
And then to pass that number to the block, we're going to yield the number and then to pick it up.
145
00:07:45,400 --> 00:07:48,000
Inside the block, we're going to have another block parameter.
146
00:07:48,000 --> 00:07:52,000
Separate a comma here and this is going to be the number.
147
00:07:52,000 --> 00:08:00,000
So whatever the value of the number is here when the block is called will be substituted in for this block parameter.
148
00:08:00,000 --> 00:08:04,200
If we run this, Larry rolled a five, a four, and a six.
149
00:08:04,200 --> 00:08:08,000
So we're passing in that random number as we would expect.
150
00:08:08,000 --> 00:08:09,200
All right, so let's mix it up.
151
00:08:09,200 --> 00:08:12,800
Let's yield first the number and then the name Larry.
152
00:08:12,800 --> 00:08:14,600
Yeah, the order of these is pretty important.
153
00:08:14,600 --> 00:08:19,200
If we did number and Larry, what are we going to get when we run the block this time?
154
00:08:19,200 --> 00:08:24,200
Well now it says five rolled a Larry in four rolled a Larry and depending on the random number,
155
00:08:24,200 --> 00:08:26,400
it's always the number rolled Larry, right?
156
00:08:26,400 --> 00:08:33,000
So what happened here is the number got substituted for name and Larry's name got substituted for the number.
157
00:08:33,000 --> 00:08:37,600
So the order in which you pass the parameters here is obviously very important.
158
00:08:37,600 --> 00:08:43,400
All right, so let's put it back to Larry a number and then let's add mo and a number.
159
00:08:43,400 --> 00:08:47,200
All right, we'll yield twice.
160
00:08:47,200 --> 00:08:51,400
We'll just copy that line and we're going to have mo yield a lot number.
161
00:08:51,400 --> 00:08:53,800
Because we know we can call yield multiple times.
162
00:08:53,800 --> 00:08:57,400
Larry rolled a five, mo rolled a five.
163
00:08:57,400 --> 00:08:59,600
Now Larry rolled a four, mo rolled a four.
164
00:08:59,600 --> 00:09:01,400
We've got some random number stuff happening.
165
00:09:01,400 --> 00:09:06,600
It's the same number because we're just computing the number once and then yielding it to the block,
166
00:09:06,600 --> 00:09:09,600
changing the name each time, but it's the same number.
167
00:09:09,600 --> 00:09:15,200
Now the cool thing about this is the method does the actual rolling and passing in the name,
168
00:09:15,200 --> 00:09:19,000
and then the block does whatever it wants with the name and the number.
169
00:09:19,000 --> 00:09:24,400
So these two concerns are decoupled in terms of the design technique.
170
00:09:24,400 --> 00:09:29,800
The block does one thing and the method does something else and the two things are different.
171
00:09:29,800 --> 00:09:34,400
We can have different things happening inside of this roll method if we wanted to.
172
00:09:34,400 --> 00:09:36,600
Here's a slow motion replay of that.
173
00:09:36,600 --> 00:09:41,600
When the roll method is called, the first line runs and prints a starting method.
174
00:09:41,600 --> 00:09:48,200
The second line then runs, returns a random number, say four, and assigns it to the number variable.
175
00:09:48,200 --> 00:09:50,400
Then the method yields.
176
00:09:50,400 --> 00:09:55,200
But what's different this time is that yield passes, or you can think of it as hands-off.
177
00:09:55,200 --> 00:09:57,200
It's two parameters to the block.
178
00:09:57,200 --> 00:10:01,200
It doesn't know what the block is going to do with these, and it doesn't care.
179
00:10:01,200 --> 00:10:03,800
It only knows to pass them along.
180
00:10:03,800 --> 00:10:07,840
When yield is called the block parameters name and number are assigned the values,
181
00:10:07,840 --> 00:10:13,240
this is Larry and four respectively, and the block is executed, printing out Larry rolled a four.
182
00:10:13,240 --> 00:10:18,040
The method then yields again and again it passes two parameters to the block.
183
00:10:18,040 --> 00:10:23,840
Notice the value of the number variable is still four, so the block prints, curly rolled a four.
184
00:10:23,840 --> 00:10:29,440
Control then returns back to the method and the method prints, back in method, and we're done.
185
00:10:29,440 --> 00:10:33,240
So we saw that with methods like select, the block returns a value,
186
00:10:33,240 --> 00:10:36,840
and then based on that value, the method does something.
187
00:10:36,840 --> 00:10:41,240
Yeah, so we've seen that methods can pass parameters to the block,
188
00:10:41,240 --> 00:10:45,040
but the block can actually return the result back to the method.
189
00:10:45,040 --> 00:10:47,040
So let's see how that works.
190
00:10:47,040 --> 00:10:51,240
So let's say we want our block to return the number doubled.
191
00:10:51,240 --> 00:10:53,440
Okay, so we just want to multiply the number.
192
00:10:53,440 --> 00:10:58,440
The last line in this block will just say number times two like that.
193
00:10:58,440 --> 00:10:59,840
Now here's the thing.
194
00:10:59,840 --> 00:11:05,640
The value of the last expression that's evaluated in the block, which is this expression here,
195
00:11:05,640 --> 00:11:10,840
is automatically passed back to the method as the value of yield.
196
00:11:10,840 --> 00:11:15,840
So if we go back up here into our roll method, I'm going to drop a mo out of here for just a second.
197
00:11:15,840 --> 00:11:21,240
Yield calls the block the block implicitly returns whatever this evaluates to,
198
00:11:21,240 --> 00:11:24,439
and we can capture that by simply assigning it to a variable.
199
00:11:24,439 --> 00:11:25,640
We'll call it result.
200
00:11:25,640 --> 00:11:28,640
You could call it anything you want here, and also I should point out,
201
00:11:28,640 --> 00:11:31,840
you can use parentheses on yield, we're passing in multiple parameters.
202
00:11:31,840 --> 00:11:36,840
So the method is giving parameters to the block when yield is done,
203
00:11:36,840 --> 00:11:41,840
the result of the block is then assigned to this variable called result.
204
00:11:41,840 --> 00:11:44,640
And then I'm going to drop out some of this put-ess clutter up here.
205
00:11:44,640 --> 00:11:52,840
I'm using this one at the bottom, I'm just going to say the block returned whatever that result is.
206
00:11:52,840 --> 00:11:57,640
Okay, if we run this now, let me roll the four, so we yield it to the block,
207
00:11:57,640 --> 00:12:00,640
and then it's at the block returned eight.
208
00:12:00,640 --> 00:12:06,439
So let's say at the bottom of our block we put hello, what does it return then?
209
00:12:06,439 --> 00:12:07,439
Yeah, that's kind of instructive.
210
00:12:07,439 --> 00:12:09,439
Let's just say we have a string.
211
00:12:09,439 --> 00:12:10,840
She said hello down here.
212
00:12:10,840 --> 00:12:14,840
If we run that now, it just says the block returned hello.
213
00:12:14,840 --> 00:12:16,840
That's the last expression in the block.
214
00:12:16,840 --> 00:12:21,040
It's returned and gets assigned to this variable result.
215
00:12:21,040 --> 00:12:24,640
Now, a gotchip crops up here again, and you probably know what it is,
216
00:12:24,640 --> 00:12:27,640
which is if you do something like put-ess hello,
217
00:12:27,640 --> 00:12:31,240
as you want to print hello out to the console as part of running this block.
218
00:12:31,240 --> 00:12:33,840
Well, you now know that it's going to print hello to the console,
219
00:12:33,840 --> 00:12:36,840
but the put-ess method itself returns nil.
220
00:12:36,840 --> 00:12:39,040
So this block is going to end up returning nil.
221
00:12:39,040 --> 00:12:41,640
If we run that, we actually see the block returned,
222
00:12:41,640 --> 00:12:44,640
but because the value is nil, nothing is printed out there.
223
00:12:44,640 --> 00:12:45,840
So just be aware of that.
224
00:12:45,840 --> 00:12:48,640
Whatever the last expression in your block,
225
00:12:48,640 --> 00:12:50,439
whatever it evaluates to,
226
00:12:50,439 --> 00:12:53,240
will be the result of running that block,
227
00:12:53,240 --> 00:12:57,840
and it will be the return value of the yield call.
228
00:12:57,840 --> 00:13:01,440
So here's a recap of everything we just learned.
229
00:13:01,440 --> 00:13:04,440
First off, the role method generates a random number.
230
00:13:04,440 --> 00:13:06,040
Say three.
231
00:13:06,040 --> 00:13:08,440
Next, we yield control to the block.
232
00:13:08,440 --> 00:13:11,840
Any parameters to the yield statement are passed directly to the block
233
00:13:11,840 --> 00:13:13,440
as block parameters.
234
00:13:13,440 --> 00:13:16,440
Here we pass Larry and the number three.
235
00:13:16,440 --> 00:13:19,640
We'll often see the parameters to yield without parentheses.
236
00:13:19,640 --> 00:13:21,240
They're optional.
237
00:13:21,240 --> 00:13:25,240
The code in the block then runs and prints out Larry World 3.
238
00:13:25,240 --> 00:13:28,840
The last expression in the block multiplies the number by 10.
239
00:13:28,840 --> 00:13:33,840
That value 30 is automatically returned to the method as the value of yield.
240
00:13:33,840 --> 00:13:36,640
To capture this value, we assign it to a variable,
241
00:13:36,640 --> 00:13:38,440
which we call result.
242
00:13:38,440 --> 00:13:41,240
The method then prints the block returned 30.
243
00:13:41,240 --> 00:13:44,640
So now you know how to write your own method that calls a block
244
00:13:44,640 --> 00:13:46,640
and captures its result.
245
00:13:46,640 --> 00:13:48,640
So you ready to give it a try yourself?
246
00:13:48,640 --> 00:13:50,440
Well, give it a go in the exercise.
247
00:13:50,440 --> 00:13:55,240
Next up, we'll use yield to write iterator methods for our own collection classes.
248
00:13:55,240 --> 00:13:56,240
That's right.
249
00:13:56,240 --> 00:14:00,840
We're going to create a movie cue full of movies like action movies, sci-fi movies,
250
00:14:00,840 --> 00:14:22,240
drama movies, comedy romantic comedy movies, documentaries.
23337
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.