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?
source to share
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
source to share
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}
.
source to share