>> [music]. Let's now discuss arrays. These are the most common data structure in Ruby programs. So we can't do too much more Ruby programming without them. And as we'll see in the next segment, they're also an excellent vehicle for seeing how Ruby supports higher order programming, and functional programming styles. So, there's lots of special syntax, and many provided methods for the array class. You'll probably want to consult the documentation to find things when that you're interested in. We'll just scratch the surface here and show you some of the possibilities. What an array is, is basically something that holds any number of other objects, and is indexed by some number. So, you can get the third element, or the fifth element, or the zeroth element. And there's special syntax to get the i-th element, where a is some array object. You write i in brackets after the a. That just sends the message to a, that you want the i-th element. And you can set the i-th element with the corresponding center method, where you write a bracket i equals e. Now arrays are common in many programming languages. This is the common syntax for them. But compared to other languages, Ruby's arrays are much more flexible and dynamic. They let you do almost anything. Almost nothing you can do with an array is actually an error. They just come up with some sensible thing to do. And as a result, arrays can be used for almost anything in Ruby. Any kind of data structure even though they might not be the most efficient thing. Often in small scripts or simple programs, people prefer the convenience and flexibility over the sort of efficiency in error detection of arrays in other programming languages. So mostly, what I'll do now is just show you a whole bunch of examples using irb, so that we get the hang of it. So first of all, you can make an array with just comma separated values inside of brackets. So, a is now a variable that holds the array with four elements where the second element is 7, and the zeroth element is 3. Like in most programming languages, arrays start counting their index positions from zero. So, if you say a sub 4, that's not actually in the array. In many languages, you'll get an array bounds error for this. But Ruby just gives you back the nil object. And the same would happen if we asked for the thousandth element of the array. If you ask for the size of the array, you get the number of elements currently in it, that is four. Let's see, you would probably think that minus 1 would return nil, since that's clearly outside the bounds of the array, but no Ruby interprets negative indices of just counting from the current end of the array. So, i minus 1 will return 9. And i minus 2 will return 7. Whereas, i minus 4 will return 3. And i minus 5 will return nil, and so on. So, we can also update array elements. So if we a, say a sub 1 equals 6. Now, if we print out the array. We see that, indeed, 6 is in the first index position. What if you assign something outside the bounds? Surely this is an error, right? Nope, it's happy to assign to that. And what's even stranger is we now have a fourth b a index four and an index five. You'll see that it filled in enough array entries with nil objects in order to make room for that 14 we added to the sixth position. So if I assign to the 1000th position, I would now have an array with 1001 entries in it, okay? So, indeed if you now ask a dot size, you see that the length, the size is now 7. We're in a dynamically-typed language, so we can put absolutely anything in this array. How about putting a string in a sub 3? We can put an instance of any class, any kind of object into our array, and that will work just fine. As I mentioned, there's lots of operations and methods to find on arrays. We've even define some of the arithmetic operators on arrays in, in ways that you might imagine is reasonable. So, for example, if I take an array like a, and I add to it another array, that just appends things onto the end. So, b is in fact now this let's see I guess 9 element array, which is different than a, which is still the 7th element array. I can't possibly show you everything you can do with arrays, but here's one that I discovered which is kind of nice. The pipe operator takes two arrays and returns an array containing the elements of either, like plus, but it removes any duplicates. So, in fact, you get back an array here that just has three elements, 3, 2 and 1, because any other elements would be duplicated in the result. Okay, so that kind of shows you the flexibility of arrays. Now let's see how we can use them for all sorts of things. So given that arrays are so flexible, there's no reason for separate tuples in Ruby. Let's, if you want to tuple then just use an array, right? So here's a 3-element tuple that, you know, is false. Just string hi and 7, and you can get the last thing out of it with triple bracket 2. So, this is a perfectly good tuple. So why would you do anything else? But more than that, arrays also can have sizes that are growing or shrinking or chosen dynamically. So, let me show you a different way to make an array. Not on this line, but on the next one. Here, I just want to emphasize that we could have some number x that could be computed at run time. So, x is 20 from some arbitrary computation. And then, you can say array.new of x. Alright? And you get an array of length 20. Now, if you wanted to initialize the elements, you can do that with blocks. This is the subject of the next segment. But here's a different version, that's also an array of 20 elements, but they're all initialized to 0. Or you can even make different elements initialized to different things. Here's a 20 element array of 0 minus 1, minus 2, up to, or I guess, down to minus 19. So, arrays can be tuples, they can be things of arbitrary size. What else could they be? Well, it turns out they make perfectly good stacks. So a stack is something with operations push and pop, where things are popped in last in, first out order. These are ubiquitous in computer science. We saw call stacks earlier in the course. So, if we just take our old array a here, it turns out that all arrays have a method push, which pushes, which adds an element to the right side. So, you'll see I just pushed 5 onto the right there, I could push 7. And now if I pop, I get a 7 back and an array no longer, a no longer has that 7. I could pop again, and I would get a 5. I could pop again, I would get a 14. And now my array is shorter. So, I'm essentially using an array as a stack. And Ruby's arrays are so flexible, why would you define your own stacks when you can just use these push and pop methods? So if we can do stacks, can we use queues? So a queue is like a stack, except instead of things coming off in the reverse order that they're put on, they're taken off in the same order they're put on. So, it is like queuing up. The person who gets in line first, gets served first in a properly functioning queue. So, I still have this a. I could push 11. That would put things on the right. The way to pull something off the left, off the beginning is the shift operator. It's called shift because when I say a.shift, like pop, I get one of the array elements back. Here, a 3. But everything's been shifted over. And indeed, now, a sub 0 is not 3 anymore, it's 6. And a sub 1 is 7. And if I shift again, then a sub 1 is the string high. So, if I use a combination of push and shift, I have a queue. I could also put things on the front of the line. So, if you want to skip ahead to the front of the line, you can unshift with 19. And now my array indeed has a 19 on the front, and if I do a shift, I get the 19 out. So arrays support all of these things. So now that we've seen that they're that flexible, you can put things on the front, on the back. You can slice them. You can dice them. You can grow them. You can shrink them. Let's talk about aliasing. So, arrays are objects. So, our previous discussion of aliasing still applies. If I say something like d equals a, then d is this array, and a is this array. And as we'll see in just a second, they are aliases. But if I did something like e equals a plus this empty array, well, the plus operation always returns a new array. So, e has all the same contents. But e is not aliased with a and d. So let me show that to you. Alright? So, d bracket zero is 7. Alright? If I now assign into a sub 0, 6. Then d sub 0 is now 6, a sub 0 is now 6. But e sub 0 is 7. So that's is our aliasing story, always nice to have a short example to show what is an alias and what is not. Let me just show you a few more things to wrap things up. There's tons more to learn about arrays. Let me show you one more array. How about 2, 4, 6, 8, 10, 12 14, okay? So it turns out, what if you wanted part of this array? So there's these things called array slices. So you could say, I want elements 2 through 4 and you would get back a new array with 6, 8, 10 and 12 which is, let's see elements 2, 3, 4. I'm surprised that oh, it's, I see, it starts at element 2 and it gives me 4 elements. So that's fine. Here is something a little stranger, you can actually assign this way. When you assign in, you don't have to put the same number of elements. So after I do this, f is shorter. I replace 6, 8, 10 and 12 with 1 and 1. Showing yet again that arrays are this very flexible data structure. They're really an arbitrary mapping from numeric indices to values, and that's how you have to think of them. Finally, the most common thing to do with a collection of data is to do something to all of them. Map over them, do a reduce over them, see if something's true of any of them, and that's really what the next segment is about. But to give you a little precursor that you really can do things with arrays, here's a little array with four elements. And I could say to each of them, let's put a, let's print i times i. And I have to explain in the next segment what this means, but there did actually print all them. And, of course, I could do this with any array, for example, f. So that's your flexibility over arrays. You'll have to consult the documentation to find more methods. In general, if you can think of a general method over arrays that probably lots of people would want, not just you, it's probably already defined in the library, and it's a good idea to go look it up. Other than that, remember that arrays can be good for tuples, lists, stacks, queues, and what are called arrays in other programming languages. And we'll continue to use them for the rest of our study of Ruby.