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?

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? 
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.
> 
> 
> I'm not sure what looping logic you're talking about.  There are no
> loops here, nor any hashes.  Array access syntax looks the same as
> hashes.  If you think there are hashes because of the block braces
> { }, it's an unfortunate thing that they share the same syntax, but
> generally whether it's a block or an array is pretty clear from the
> context.

I thought because of the [][] that it was accessing a hash. Isn't this 
how you access a hash inside an array?


>> I'm using this code in a simple 2d array. It was working but then I
>> changed all of my ranges from (0...value) to (1..value) [I used ranges
>> to populate my 2D array with hashes] I now get the error message:
> 
> 
> What's probably happening is that you're going beyond the initial size
> of the array (width, height).  If your array is 2 by 3 and you try to
> do:
> 
> x[10, 20] = 5
> 
> Internally it tries to do @data[10][20] = 5.  @data[10] is past the
> end of the array, so its value is nil, so @data[10][20] = 5 becomes
> nil[20] = 5.
> 
> Giving the error message:
> 
> 11:in `[]=': undefined method `[]=' for nil:NilClass (NoMethodError)
> 
> You could probably fix that by changing the []= method to something
> like:
> 
> def []=(x, y, value)
>    # If @data[x] is nil, create it as an empty array
>    @data[x] ||= Array.new
>    @data[x][y] = value
> end
> 
> If you do that, you should also fix [] to create missing values too:
> 
> def [](x, y)
>    # If @data[x] is nil, create it as an empty array
>    @data[x] ||= Array.new
>    @data[x][y]
> end

I think I know what's going wrong. The size of the array hasn't changed, 
but where I start entering values into the array has, which means 
there's no room for the last row and column. Basically what I've done is 
change (0...5), which is 0 1 2 3 4, to (1..5), which is 1 2 3 4 5 - both 
the same size. But when I use this new range to iterate through my array 
the first position addressed is now 1; so I'm trying to fit 5 units into 
a 5 unit box without filling up the space in the box allocated to unit 
1.
-- 
Posted via http://www.ruby-forum.com/.