So I wrote a 2D array class for a project I’m working on, in Ruby.
It’s simple enough: the initialize creates a Square 2D array, of a size dictated by its argument, called @contents.
I overload the [] operator to make the data within the object accessible, like so:
def [] (x, y)
@contents[x][y]
end
def []=(x, y, z)
@contents[x][y] = z
end
I add an each method to it, so that I could mix in the enumerable module, and give it some functionality, like so:
def each
i, j =0,0
while (i<@size)
while(j<@size)
yield @contents[i][j]
j+=1
end
i, j = i+1, 0
end
end
and I gave it a to_s method, like so:
def to_s
@contents.each{|i| puts i}
end
Now, I create a new instance of this 2D array object in a new file, and try to populate it. Initally,I did this manually, with nested loops, like so:
j, i, k= 0, 0, 0
puts " size = #{@size}"
while (i<@size)
while(j<@size)
@2Darray[i,j], k, j= @array[k], k+1, j+1
end
i, j=i+1, 0
end
And that works just fine. the to_s method will print out the array perfectly. I realized though, that these nested loops might not have been the ‘ruby way’ and tried to do it with itterators. I had already implimented an each method, so I tried to subsitute the above, with the following:
j=0
@2Darray.each{|i|
i = @array[j]
j += 1
break unless j < size
}
But, unfortunately, this doesn’t work. It runs just fine, but when the to_s is called, it prints line after line of nothing. ie, it prints out an array of empty arrays.
I thought it was my .each method, but that works fine when the to_s method calls it. I thought it might have been my []= method, but that works fine when I use nested while-loops.
Now I’m thinking it must be a problem with scoping. in my each-loop above, |i| is a local variable, am I right? So that I assign the value of array[j] to i, but i is just a copy of the (empty) position which I want to fill, yes?
So, firstly, am I on the right track, or is my problem somewhere else entirely? If so, where, if not: How can I modify my each-loop above, to make assignments to the data within @2Darray, instead of just changing the value of the |i| place-holder.
Apologies for my verbouseness, and thank you for your time! Any help would be appreciated.
That is not the way you can populate whatever @2Darray is.
iis a block local variable. The #each method effectivelly calls your block (the iterator) for every element, passing a reference to the element in that block local variable. Assigning to a variable will not change the object the variable had been pointing to previously.The “ruby way” to populate it would be to provide an instance method that accepts the data to be used, that then uses whatever loop is appropriate.
For what it’s worth, your
while(i<@size)loops can well be expressed as@size.times