C 里的标准数组定义是定长。但 ruby 里定义了 a[0],但也可以访问 a[50] ,但访问更多 a[100000] 进程可能会被 kill。所以我猜测 ruby 里的数组可能是一种方法?方法名就是 [],参数就是里面的下标。
对么
[]
的本身是一个方法名。http://ruby-doc.org/core-2.2.3/Array.html#method-i-5B-5D
访问的时候,会 check 这个下标是否在这个数组里面。
定义一个[]
方法。
class A
def [](index)
"this is a [] method"
end
end
A.new[1] #=> "this is a [] method"
A.new["index"] #=> "this is a [] method"
C 里面的数组和 ruby 里面的数组不是一种东西 ruby 里面数组是一个 object, 这个 object 本质上是 wrap 一个 C 的数组 [] 是 ruby 的 Array Class 的一个方法,不仅可以越界访问数组,还可以是负数。
VALUE
rb_ary_entry(VALUE ary, long offset)
{
if (offset < 0) {
offset += RARRAY_LEN(ary); //如果是负数,就掰正
}
return rb_ary_elt(ary, offset);
}
static inline VALUE
rb_ary_elt(VALUE ary, long offset)
{
long len = RARRAY_LEN(ary);
if (len == 0) return Qnil; //如果数组为空,返回 nil
if (offset < 0 || len <= offset) {
return Qnil; //如果索引越界,返回 nil
}
return RARRAY_AREF(ary, offset);
}
array.c 里面的两个函数,根据索引访问数组的时候都是这两个函数处理的。
#7 楼 @mingyuan0715 不可能,六十年代的机器也不会 array[10000] 就爆掉吧,我机器可以 array[10*9],array[10*10] 会抛出 RangeError,bignum too big to convert into 'long'
#9 楼 @cicholgricenchos 我觉得你这个更多是解释了什么叫鸭子类型,因为你认为实现了下标读写器的类型就是数组,但无法说明数组就是方法。按照这种思路,数组的实现也可以是字典(所有的键是按数字从 0 开始递增),再如果我用链表实现,那么我也可以说数组就是链表。鸭子类型的强大之处就在于你可以专注于你可以做些什么事情,而无需过多担心你的对象到底是什么类型。
#8 楼 @africwildman 我的错,访问数组不会产生内存问题,赋值会。比如 a = [], a[1_000_000_000] = 1,内存就爆了。不过跟题主的问题无关。
我的试验结果是不会 kill 掉进程,但位数超过范围了会报错。例如,a[100000000000000000000000] ,RangeError: bignum too big to convert into
long'`