Is ruby ​​multidimensional array out of bounds compatible?

If I have a multidimensional array, I can go over the bounds in the final dimension and get a zero return, but if I go over the bounds of the non-finite dimension, I get an error. This is by design, and if so, what is the reasoning?

> ar = [ [00,01,02], [10,11,12], [20,21,22] ]
=> [[0, 1, 2], [10, 11, 12], [20, 21, 22]]
> ar[2][2]
=> 22
> ar[2][3]
=> nil
> ar[3][2]
NoMethodError: undefined method `[]' for nil:NilClass
from (irb):32
from :0

      

I understand why this is happening, but why is there no nil [] to return nil?

+3


source to share


2 answers


I don't know when Matz ever documented why it is NilClass

designed the way it is. If this is not the case, we can only guess. I assume it is based on Smalltalk behavior.

nil

can be either message usage or exception. Ruby has an exception throwing a null object.

If you have a message that has zero in it, then it is difficult to determine the object that came first to return zero in the chain, for example arr[1][2][3]

. I don't know how often this really is a problem, but it seems to be the right question. As a counterexample, Objective-C seems to do a great job with a message that has zero in it.

You can schedule NilClass

to become a message meal

class NilClass
  def method_missing(*)
    nil
  end
end

      



or just for arrays

class NilClass
  def []
    nil
  end
end

      

both do nil[]

return zero and can either break existing code

nil[][][][]
=> nil

      

+1


source


There are no multidimensional arrays in Ruby. You have an array containing arrays as elements. So if you get the first "dimension", you get another array back (or nil if you've exceeded the bounds of the outer array).

nil

is an object NilClass

that has a finite (and small) set of defined methods. And the method []

that gets called when using the syntax whatever[:foo]

is simply not defined on NilClass

. Thus, he cannot return anything.

Generally, it would be pointless to define all possible methods as nil, as this would confuse people even more and introduce a lot of hard-to-find errors.



However, if you know what you are doing and are ready to deal with the consequences, you can use a method try

that is defined in some framework (for example, ActiveSupport for Rails) but is not part of Ruby itself. He catches NoMethodError

and returns nil

. In your case, you can use

> ar[2].try(:[], 2)
=> nil

      

However, this is usually discouraging as it makes debugging difficult. Instead, you should check the bounds before trying to access the array (for example with array.length

), or using include looping constructors such as ar.each {|e| puts e}

.

+3


source







All Articles