[MUSIC] In this segment, I want to start our study of Ruby blocks. Blocks are probably the strangest feature in Ruby, compared to similar features in other languages. But they're also one of the most convenient and most frequently used. So it's worth studying them. And the great news is they are so close to closures, that we'll find them convenient and useful from the very beginning. So let me start with what is normal and closure like about them. Blocks are things that you can pass to other methods essentially as anonymous functions, so that the callee can then call that function and use them. Like function closures in other languages we've studied, they can take zero arguments, one argument, two arguments and so on. And liked closures, they use lexical scope. When the callee calls the block, we evaluate the block body in the environment where the block was defined not where the block is being called. So the examples you see on the slide start to show you some of the syntax. A block, unlike a lambda in Racket, or a fnarrow in ML, is just put between braces. So on this first line we're passing a block that prints "hi" as an argument to this method 3.times. It's just passed differently than other arguments and we'll talk more about that in a second. Similarly on this line and then on the last one. This one on the last one is on the last line is a blocked that takes an argument x. So let's real quick type all these in so we can see what they're doing. So 3.times, times is just a method that's defined on numbers, and it takes in this block by just putting it next to the method call. And it runs the block that number of times. So, this will print hello three times. If you have an array, there is an each method and that each method calls the block one's for each element of the array. So, this will also print three times because, the array has three elements. Now much more useful is to do something with the actual elements you're being passed. And to do that, when you call each on an array, you can take in an argument, how about x. And then we can just print that, it'll convert these numbers to strings and it prints out 4, 6, 8. And just to emphasize that these things really do have lexical scope, let's have a variable here where we are going to define our block. How about i = 7 and now let's call each on an array holding 4, 6, and 8. Where we ask if i is greater than x then let's put print, lets say x + one, otherwise lets do nothing. And that will print 5 and 7, because the 8 is greater then the 7, so we didn't do anything for the last element of the array. So this is higher order programming in Ruby, this is how you normally do it, and so far I tried to make these things seem very normal. Now let me show you some things that are actually a little bit strange. So one strange thing is that you can pass either 0 blocks, or 1 block to any method call. In any message you get to pass 0 or 1, you can't pass multiple blocks. But you can pass one, now if you pass one the callee might ignore it. The callee might give an error conversely when you don't send one. The callee can even do different things based on whether or not you send one. So this is separate from the normal arguments. You pass your normal arguments in parenthesis, separated by commas and then on the side literally syntactically next to it. You either do pass a block or you do not, okay? So, the syntax is as we've seen just brace and then some expression that is the body. Or if you want your block to receive arguments when the callee calls it, then you put them between these pipe characters and separate them with commas. So this last example here takes two arguments which we'll call x and y. I'll show you in the next segment how a callee can use a block, here we're just passing blocks and letting the library methods that take blocks call our blocks in their bodies. There's a second syntax I'll show you in a bit. That instead of braces, you can use do for the left brace and n for the right brace. This is the preferred style usually when your blocks are multiple lines long. Whereas the braces are usually preferred for one-line blocks. And other than that, they're almost equivalent. They only have syntactic differences in terms of precedence and things like that. So, what are these things so good for? I mean, 3.times was nice. Well we already saw one neat thing, which is this is how we can apply the same code to every element of an array. By using the each method on array. But it turns out the standard library in Ruby is full of methods that expect blocks to be passed to them. So, because the standard library make such great use of what is essentially functional programming and higher order functions, Ruby programmers almost never use explicit loops. There are loops in the language but almost no one uses them. Because all the standard things you need to use loops for, there's a more convenient way to just take some method that's in the standard library and pass it a block. So let me just for the rest of this segment show you a bunch of examples including those that were on the slide. But by typing them out I think we we will get a better sense and I will mostly just do things over array. So let's create a new array that takes size 5 and it turns out the initialize method for the array class will take a block. It's optional, if you don't pass it, then you just end up with 5 nils. But if you do pass it, you can actually have it take the index of the array and have that compute the initial value in that position. So with this call here, I end up with 4, 8, 12, 16, 20, okay? So now, if I did something like call a.each with something that prints x * 2. It's going to print on one line each, 8, 16, 24, 32, 40. And this is essentially just applying the same code to every line width in the array. And it's certainly more convenient than some explicit for loop, or while loop, like you see in other languages to iterate over array elements. We have other nice things in this language. How about Map. I told you Map was a common name in Computer Science. Ruby was happy to use it as well. What if mapped the computation x goes to x * 2 across the array? Then what I get is a new array, holding 8, 16, 24, 32, 40. So, I'm not printing here. I really am creating a new array. It has size 5 and its second index is 24 and so on. So that's Map, we know Map is wonderful. There's a bunch of other methods, essentially higher order functions over arrays. How about a.any?? So what this does is it applies the block to every element in the array until it finds one that the block answers true for, and then it returns true. And if it doesn't find one, then it answers false. So a.any with this computation returned true because there are elements in there greater than 7, but there are none greater than 700. So this is how you find whether some property holds, of some element of the array. As you might imagine, there's also an all. It is not true that everything in the array is greater than 7, but it is true that everything in the array is greater than minus 7. So those are useful. By the way, these methods do not require blocks. If you just pass one without the block, it sees if everything in the array in this case answers true, is true. And as I mentioned once before in Ruby, the only things that are false are false and nil. So there are no falses or nil in this array but if I did a plus an array holding false, and asked all, I would get false and similarly nil. I would get false. But anything else, I would get true. And so on. So there's a few more. There's one called inject. This is what we called reduce. So for example, if I have an initial accumulator of 0, that's the ordinary argument, and then the block requires two arguments here. The answer so far, which I'll call acc, and then the next element, which I'll call elt. And we can just add them together, and as I've shown you many times, that will sum up all the elements of the list. It tuns out in Ruby, if you leave this initial accumulator off, it will use the first element as the accumulator, which for summing will work just fine. Other times, you want an initial accumulator that's not the first element of your array, and then you pass it as the argument to inject. So inject is just Ruby talk for reduce and as long as I'm mentioning it, a.collect is the exact same as a.map. They just gave it a second name. It is sometimes called collect by others. What about filter? Well, it turns out there is no filter method. It's just an undefined method. They called it select, but it works just like what I like to call filter. So if I filter, let me just remind you of what's actually in this array, 4, 8, 12, 16, 20. And if I filter, or in Ruby talk, select for x greater than 7, I will get 8, 12, 16, 20, or if I wanted to say and x less than 18, then I would just get 8, 12, and 16. So that's all I wanted to show you with arrays. Let me show you one other thing which is really why even when you think you need a loop you can avoid it. And that is, let's just define a little method here. Where what I want to do is create the range. I'll explain what the ranges are a little bit more in a future segment. This is just an object that represents the sequence 0 up through i. Okay, and it has an each method, so it's not technically an array, but it acts a lot like one. So it has an each method. This is the other syntax for blocks I promised you that's better for multiple lines. So do is just like the left brace. So for each value j from 0 up to i, where i is the argument to this method, let's do the following. Let's first print two spaces times j. So the times operation on strings will make that two j spaces. Now in here, let's do a nested range from j up to i. And for each of those, let's have a little one-line block. So for each k from j up through i, let's print k and then a space. And then, after we do that, let's print a new line character, and then let's end this block. So this end matches the do that is four lines above. And then let's end the method. And that just defined a method. Now, I'm about to call it. You can try to figure out what it's going to do, it's just a little pretty. If I pass it 9, it prints out this nice little grid with triangles of numbers from 0 up through 9. This the sort of thing you would use nested loops for in most programming languages. We morally have nested loops here, but really, what I literally have are method calls. The each method on these range objects, passing in blocks, that then they callee uses, and this is the result I get. So that's our blocks. In the next segment we'll learn how to use blocks in our own methods, and then we'll talk more about how they're not quite fully closures.