Imr*_*qvi 6 ruby arrays ruby-on-rails-4
今天我遇到了一些奇怪的Array元素赋值行为:
arr = ["a","b"]
arr2 = [1,2]
arr.unshift(arr2) #= [[1, 2], "a", "b"]
arr.push(arr2) #=> ["a", "b", [1, 2]]
Run Code Online (Sandbox Code Playgroud)
然而,这是有道理的:
arr[0,0] = arr2 #=> [1, 2, "a", "b"]
Run Code Online (Sandbox Code Playgroud)
我知道在[0,0]第一个零中index,第二个是从该数组开始生效的元素数量index.
在我的想法中它应该与它相同unshift,但事实并非如此.
任何人都可以解释这种行为吗?
如果我们深入研究 ruby 源代码,我们会发现一个名为rb_ary_splice的函数,当使用三个参数(即索引、长度和新值)进行数组赋值时调用:
static VALUE
rb_ary_aset(int argc, VALUE *argv, VALUE ary)
{
long offset, beg, len;
if (argc == 3) {
rb_ary_modify_check(ary);
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
rb_ary_splice(ary, beg, len, argv[2]);
return argv[2];
}
[...]
Run Code Online (Sandbox Code Playgroud)
如果我们继续下去,rb_ary_splice我们就会发现奇迹发生的地方:
static void
rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
{
long rlen;
long olen;
if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
olen = RARRAY_LEN(ary);
[...]
if (len != rlen) {
RARRAY_PTR_USE(ary, ptr,
MEMMOVE(ptr + beg + rlen, ptr + beg + len,
VALUE, olen - (beg + len)));
ARY_SET_LEN(ary, alen);
}
if (rlen > 0) {
MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_CONST_PTR(rpl), VALUE, rlen);
}
}
RB_GC_GUARD(rpl);
}
Run Code Online (Sandbox Code Playgroud)
首先,它在数组中为新元素腾出空间并更新长度:
RARRAY_PTR_USE(ary, ptr,
MEMMOVE(ptr + beg + rlen, ptr + beg + len,
VALUE, olen - (beg + len)));
ARY_SET_LEN(ary, alen);
Run Code Online (Sandbox Code Playgroud)
然后通过 C 指针的魔力,它插入新元素:
MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_CONST_PTR(rpl), VALUE, rlen);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
104 次 |
| 最近记录: |