新手问题 关于 Array 的一个奇怪的问题

chiangdi · 2014年10月02日 · 最后由 blacktulip 回复于 2014年10月02日 · 1926 次阅读

是从 ruby-doc 上看到的,http://www.ruby-doc.org/core-2.1.3/Array.html#method-i-slice

a = [ "a", "b", "c", "d", "e" ]
a[2] +  a[0] + a[1]    #=> "cab"
a[6]                   #=> nil
a[1, 2]                #=> [ "b", "c" ]
a[1..3]                #=> [ "b", "c", "d" ]
a[4..7]                #=> [ "e" ]
a[6..10]               #=> nil
a[-3, 3]               #=> [ "c", "d", "e" ]
# special cases
a[5]                   #=> nil
a[6, 1]                #=> nil
a[5, 1]                #=> []
a[5..10]               #=> []

我试了下确实是这样的, 但都是超出范围了,为什么 a[6,1]nil, a[5,1] 却是 [] ,这是什么道理?

# ary[start, length] → new_ary or nil
# http://www.ruby-doc.org/core-2.1.3/Array.html#method-i-5B-5D
a[6, 1]                #=> nil
a[5, 1]                #=> []
VALUE
rb_ary_aref(int argc, VALUE *argv, VALUE ary)
{
    VALUE arg;
    long beg, len;

    if (argc == 2) { /* 两个参数 */
        beg = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
        if (beg < 0) {
            beg += RARRAY_LEN(ary);
        }
        return rb_ary_subseq(ary, beg, len); /* 注意此处,查看ruby源码 */
        /* https://github.com/ruby/ruby/blob/88cbfc0d10f6d449a41127db365389951b87ee51/array.c */
    }
    /* 以下代码省略 */
    if (argc != 1) {
        rb_scan_args(argc, argv, "11", NULL, NULL);
    }
    arg = argv[0];
    /* special case - speeding up */
    if (FIXNUM_P(arg)) {
        return rb_ary_entry(ary, FIX2LONG(arg));
    }
    /* check if idx is Range */
    switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
      case Qfalse:
        break;
      case Qnil:
        return Qnil;
      default:
        return rb_ary_subseq(ary, beg, len);
    }
    return rb_ary_entry(ary, NUM2LONG(arg));
}
VALUE
rb_ary_subseq(VALUE ary, long beg, long len)
{
    VALUE klass;
    long alen = RARRAY_LEN(ary); /* 5 */
    if (beg > alen) return Qnil; /* a[6, 1] = nil */
    if (beg < 0 || len < 0) return Qnil;
    if (alen < len || alen < beg + len) {
        len = alen - beg; /* len=5-5=0,  a[5, 1] = [] */
    }
    klass = rb_obj_class(ary);
    if (len == 0) return ary_new(klass, 0);
    return ary_make_partial(ary, klass, beg, len);
}

#1 楼 @flowerwrong 楼主问的是设计原因,不是问实现原理。 @chiangdi 这里有个 post 对此有所解释 ,大意是为了可以在数组尾部增加元素。其中提到数组中 single argument index 和 first argument in two arguments 的含义有微妙的区别,可供参考。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号