All language subtitles for pragstudio-ruby-blocks-04-yielding (Transcribed on 27-Apr-2023 21-17-08)

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified) Download
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranî)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
fa Persian
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

So now that we're comfortable calling built-in Ruby methods, the take blocks, we're ready

to write our own methods that take blocks.

Yeah, and this can really take you Ruby game up a level.

We're going to start with a simple example in this module, but then we'll incrementally

work up to more realistic use cases in the coming modules.

So let's say we have this block attached to the times method here.

And obviously when we run this, it's going to print out three times running the block.

It's going to be very nice to realize that we've already seen how this works.

But now we want to change things around a little bit.

Instead of calling the times method, we want to associate a block with our own method,

a method that we're going to define.

And we're going to call that method run my block just to keep it really simple for now.

When that method runs, we want it to call the block just once.

So let's go ahead and define the method.

We can be called run my block. And I'm going to start off just to print out there says

starting method.

And then it's going to end by saying back in method.

But between these two lines, we actually want it to call the block.

And the way we do that is by using yield.

If we run this, we see starting in method running block and then back in method.

So what happened is when the method was run here, it printed out starting in method.

Then when yield was called, it passed control over to the block, which was here.

And then it printed out running block.

Then when the block was done, control ended up back on the next line,

which printed out back in method.

We can actually use this method to call any block.

So we could change what the method does.

Like perhaps the method says the time is now whatever.

Sure, it doesn't matter what the block does.

The time is now.

And then Ruby will get the current time time about now.

Right?

Our run my block method doesn't care what the block does.

It just yields to it.

So inside the block, we can have any Ruby code we want.

And every time we run that, it just prints out the current time.

Now that calls the block once, but we saw how three dot times actually call the block multiple times.

Three times in that case.

So how does that work?

So let's start over with the new method.

Let's write a method that rolls the dice.

Sure, let me just zap this out of here.

We want a method called roll.

So it's going to roll the dice and then it's going to yield control over to our block.

Inside of the block, we're going to generate a random number.

Ruby, we can do that using the ran method and then just pass it a range of numbers.

1 to 6.

And then let's print out you rolled whatever number.

Okay.

Now, to make that work, we need to define the roll method.

All right.

Roll.

What's it going to do?

Well, I'm going to go ahead and say starting method just so we see that.

And I'm going to say back in method.

What's this we have before?

And then between those two lines, we need to call the block.

We know to do that calling yield.

We can actually call a yield multiple times.

Every time we call a yield, it's going to call the block.

So we want to roll the dice three times.

We would call yield three times.

If we go ahead and run that, we see we get U rolled A and a random number each time.

And it called that block three times just as we expected.

What an animation help?

Why have one for you?

Here's a roll method that yields to the block twice and how we called the method with

the block.

When the method is called, the first line runs and prints starting method.

The second line then runs which yields control to the block.

Effectively, whenever yield is called, the method stops what it's doing and lets the

block do its thing.

In this case, the block generates a random number and prints it out.

Once the block is done executing, control returns back to the method.

So the third line of our method runs and we yield once again to the block, the block runs

and prints out a second random number.

We then return back to the method.

The method prints out back in method and we're done.

Notice here the method runs once and the block runs twice.

You can call yield as many times as you want to inside the method.

In fact, that's exactly what iterator methods do.

Now, it's important to keep in mind that the block isn't a method parameter.

We don't see a parameter called something like the block right here.

There's no name for the block at all.

There's nothing in the method signature that says it even expects a block.

It's just a regular method definition.

Every method accepts a block and there's nothing special we have to do to accept that

block.

But we do have to call yield to actually run the block.

So let's see what happens if we don't call yield.

I'm just going to go back down to one yield call right here and I'm going to comment

it out.

And try to run the code.

Well, it expected the block we didn't get in the error, but you notice it just printed

out starting method back in method.

So it basically just ignored the block that was attached to the method.

So now it happens if we do yield to the block, but we don't have a block associated

to that method.

So I'm just going to comment out the block right there.

We're calling roll without a block, but we're yielding inside that method.

So now if we run it, we get an error. It says no block was given.

We get this local jump error.

So whenever you call yield, it's expecting a block to be attached to it and then call.

If you don't have a block, you're going to get an error.

So if yield is called, there must be an associated block.

So what if we want the method to work if a block is passed and if the method doesn't

get passed a block?

We're going to call yield, we only want to call it if a block was attached.

We can check for it by saying if and then using the method block underscore given question

mark that returns true if there's an associated block and false otherwise.

So if there's not a block, this line of code won't be run at all.

There's a block.

It will yield to it.

Okay, so we've got roll set up.

There's no associated block there.

If we run it now, we shouldn't get an error and we don't.

It just doesn't do anything between starting method and back in method.

And if we go back to attaching our block here, pull that back up in line and we run it,

well now yield to the block because a block is given.

So we saw how blocks can take parameters when we were using the built in Ruby methods.

Well, we can do the same thing with our methods.

Yeah, for example, the times and the up to method in particular, we saw that it passed

the number to the block.

So let's rearrange our method so it passes a parameter to a associated block.

So let's have the method pass in the name of the person rolling the dice.

Okay, well, we know that block parameters go inside the block after do here and they go inside

of vertical bars.

So the name of this parameter is going to be called, well, it's actually called name.

And then we can print out name of whoever rolled a number.

Okay, we'll just change that over to name there.

Okay, so we need to supply a value to name when this block is invoked or when it's run.

We do that inside of our roll method.

I'm going to go ahead and drop off this if block given because I think you know how that works.

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.

Now you can use parentheses here if you want.

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.

So whatever we supply here is a parameter to yield will get substituted in as the value of that block parameter.

So if we run this now, Larry rolled a five.

What if we also want to pass in the random number?

Yeah, we can actually pass that as a block parameter as well.

Let's say our roll method is going to generate the random number.

So we'll put that up here inside a roll.

That's not the responsibility of the block anymore.

And then to pass that number to the block, we're going to yield the number and then to pick it up.

Inside the block, we're going to have another block parameter.

Separate a comma here and this is going to be the number.

So whatever the value of the number is here when the block is called will be substituted in for this block parameter.

If we run this, Larry rolled a five, a four, and a six.

So we're passing in that random number as we would expect.

All right, so let's mix it up.

Let's yield first the number and then the name Larry.

Yeah, the order of these is pretty important.

If we did number and Larry, what are we going to get when we run the block this time?

Well now it says five rolled a Larry in four rolled a Larry and depending on the random number,

it's always the number rolled Larry, right?

So what happened here is the number got substituted for name and Larry's name got substituted for the number.

So the order in which you pass the parameters here is obviously very important.

All right, so let's put it back to Larry a number and then let's add mo and a number.

All right, we'll yield twice.

We'll just copy that line and we're going to have mo yield a lot number.

Because we know we can call yield multiple times.

Larry rolled a five, mo rolled a five.

Now Larry rolled a four, mo rolled a four.

We've got some random number stuff happening.

It's the same number because we're just computing the number once and then yielding it to the block,

changing the name each time, but it's the same number.

Now the cool thing about this is the method does the actual rolling and passing in the name,

and then the block does whatever it wants with the name and the number.

So these two concerns are decoupled in terms of the design technique.

The block does one thing and the method does something else and the two things are different.

We can have different things happening inside of this roll method if we wanted to.

Here's a slow motion replay of that.

When the roll method is called, the first line runs and prints a starting method.

The second line then runs, returns a random number, say four, and assigns it to the number variable.

Then the method yields.

But what's different this time is that yield passes, or you can think of it as hands-off.

It's two parameters to the block.

It doesn't know what the block is going to do with these, and it doesn't care.

It only knows to pass them along.

When yield is called the block parameters name and number are assigned the values,

this is Larry and four respectively, and the block is executed, printing out Larry rolled a four.

The method then yields again and again it passes two parameters to the block.

Notice the value of the number variable is still four, so the block prints, curly rolled a four.

Control then returns back to the method and the method prints, back in method, and we're done.

So we saw that with methods like select, the block returns a value,

and then based on that value, the method does something.

Yeah, so we've seen that methods can pass parameters to the block,

but the block can actually return the result back to the method.

So let's see how that works.

So let's say we want our block to return the number doubled.

Okay, so we just want to multiply the number.

The last line in this block will just say number times two like that.

Now here's the thing.

The value of the last expression that's evaluated in the block, which is this expression here,

is automatically passed back to the method as the value of yield.

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.

Yield calls the block the block implicitly returns whatever this evaluates to,

and we can capture that by simply assigning it to a variable.

We'll call it result.

You could call it anything you want here, and also I should point out,

you can use parentheses on yield, we're passing in multiple parameters.

So the method is giving parameters to the block when yield is done,

the result of the block is then assigned to this variable called result.

And then I'm going to drop out some of this put-ess clutter up here.

I'm using this one at the bottom, I'm just going to say the block returned whatever that result is.

Okay, if we run this now, let me roll the four, so we yield it to the block,

and then it's at the block returned eight.

So let's say at the bottom of our block we put hello, what does it return then?

Yeah, that's kind of instructive.

Let's just say we have a string.

She said hello down here.

If we run that now, it just says the block returned hello.

That's the last expression in the block.

It's returned and gets assigned to this variable result.

Now, a gotchip crops up here again, and you probably know what it is,

which is if you do something like put-ess hello,

as you want to print hello out to the console as part of running this block.

Well, you now know that it's going to print hello to the console,

but the put-ess method itself returns nil.

So this block is going to end up returning nil.

If we run that, we actually see the block returned,

but because the value is nil, nothing is printed out there.

So just be aware of that.

Whatever the last expression in your block,

whatever it evaluates to,

will be the result of running that block,

and it will be the return value of the yield call.

So here's a recap of everything we just learned.

First off, the role method generates a random number.

Say three.

Next, we yield control to the block.

Any parameters to the yield statement are passed directly to the block

as block parameters.

Here we pass Larry and the number three.

We'll often see the parameters to yield without parentheses.

They're optional.

The code in the block then runs and prints out Larry World 3.

The last expression in the block multiplies the number by 10.

That value 30 is automatically returned to the method as the value of yield.

To capture this value, we assign it to a variable,

which we call result.

The method then prints the block returned 30.

So now you know how to write your own method that calls a block

and captures its result.

So you ready to give it a try yourself?

Well, give it a go in the exercise.

Next up, we'll use yield to write iterator methods for our own collection classes.

That's right.

We're going to create a movie cue full of movies like action movies, sci-fi movies,

drama movies, comedy romantic comedy movies, documentaries.

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.