On Sat, Jul 17, 2010 at 5:09 AM, Shawn W_ <shawnw / internode.on.net> wrote:
>
> Does that mean it should work if I wanted to wrap top and bottom, and
> cap left and right, rather than the other way around? I've tried this
> but it also fell over with the same error. I would think that if
> array[100][1] won't work for the reasons you give above, array[1][100]
> should work, returning nil?
>
> Perhaps I could write a custom method for the nil class? Other than
> that, I don't know how to get around this - maybe investigate NArray, or
> add rows top and bottom that are invisible, and absorb all top/bottom
> out of bounds queries.

No, the simplest thing to do is what you've already done - write an
Array2D class to hold your array of arrays, and do some checking when
you dispatch []

class Array2D
  attr_reader :rows, :columns

  def initialize(m, n)
    @rows = m
    @columns = n
    @array = Array.new(@rows) { Array.new(@columns) }
  end

  def [](col, row)
    i = col % columns
    j = row % rows
    @array[j][i]
  end

  def []=(col, row, val)
    i = col % columns
    j = row % rows
    @array[j][i] = val
  end
end

you have the actual array, @array, as a private variable, so the only
way to access it is through your Array2D object, and your definitions
of [] and []= make sure it wraps in both directions. ( % is the mod
operator )

If you'd rather return nils for out of bounds:

def [](col, row)
  if col < 0 or col > (columns - 1) or row < 0 or row > (rows - 1)
    return nil
  end
  @array[row][col]
end

and then you need to decide what to do when assigning out of bounds.

martin