From: "David A. Black" Date: 2009-09-12T20:40:15+09:00 Subject: Re: Nooby question : multidimensional arrays. Hi -- On Sat, 12 Sep 2009, Shawn W_ wrote: > Ben Giddings wrote: >> On Sep 12, 2009, at 00:06, Shawn W_ wrote: >>> 04 @data = Array.new(width) { Array.new(height) } >> >> Create an Array named @data initially with 'width' rows. Set the >> value of each element of the array to a new array with 'height' rows. >> >> If 'width' is 3 and 'height' is 2, @data initially looks like: >> >> [[nil, nil], [nil, nil], [nil, nil]] > > I have no problem understanding this bit. An instance variable has been > created called "data". The value of this variable is unique for each > object created in this class. This variable is equal to an array inside > an array; the {} are used to pass the Array.new(height) into each part > of the Array.new(width). > >> >>> 07 def [](x, y) >>> 08 @data[x][y] >>> 09 end >> >> Create a method to access the elements like so: >> >> obj[2,0] returns the value of @data[2][0] (here it would be nil) > > I understand what this is doing but not how it works. As far as I can > see it's creating a class Array2D method named [], with parameters x and > y. So when you call this method it should look like: > > 2D_array_obj = Array2D.new(3,8) > puts 2D_array_obj.[](1,1) <-- should put whatever is in row 1, column 1. > puts 2D_array_obj[1,1] <-- but this is what works to display row 1, > column 1. > > How can you name a method [] when such syntax is used so often > elsewhere? How do those 1's get inside the square brackets? You can name it [] because the parser knows what it means in a given context. This: identifier[] always means the [] method. As for the 1's inside the brackets: that's syntactic sugar. When Ruby sees this: x[y] it automatically converts it to: x.[](y) > Then there is the line: >>> 08 @data[x][y] > Which is actually: >>> 08 a 2D array [x][y] > Is the [][] syntax a way of accessing an array inside an array normally? It really means this: @data.[](x).[](y) In other words, it's calling the [] method first on @data, then on the return value of @data[x]. > I know you can access a hash inside array using this method. I am even > using such code to substitute values into a hash inside my Array2D > object like so: > 2D_array_obj[x,y]["hash_key"] = new value > >> >>> 11 def []=(x, y, value) >>> 12 @data[x][y] = value >>> 13 end >> >> Create a method to set the values: >> >> obj[1,1] = 4 assigns 5 to the array element at of @data[1][1] >> >> After which, @data would look like: >> >> [[nil, nil], [nil, 5], [nil, nil]] > > I assume "obj[1,1] = 4 assigns 5..." is a typo and should be "obj[1,1] = > 5 assigns 5..."? > > Here we have a different syntax with []= being used. Is []= the name of > the method? Now you've explained it I know what this is doing but it's > still not clear how it works. Yes, []= is the name of the method. > I thought because of the [][] that it was accessing a hash. Isn't this > how you access a hash inside an array? It's all about method calls. [][] by itself doesn't mean array or hash or any other class of object. If you do this: x[y][z] then you're calling the [] method on x, with the argument y -- which can return an array, a hash, a string, a Person instance, anything at all -- and then you're calling [] on whatever you got back, with the argument z. David -- David A. Black, Director Ruby Power and Light, LLC (http://www.rubypal.com) Ruby/Rails training, consulting, mentoring, code review Book: The Well-Grounded Rubyist (http://www.manning.com/black2)