If we dive into the ruby source code, we will find a function called rb_ary_splice when an array with three arguments is assigned (for example, index, length and new value):
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]; } [...]
And if we follow in rb_ary_splice , we will have a place where the magic happens:
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); }
First, it creates a space in the array for the new elements and updates the length:
RARRAY_PTR_USE(ary, ptr, MEMMOVE(ptr + beg + rlen, ptr + beg + len, VALUE, olen - (beg + len))); ARY_SET_LEN(ary, alen);
Then, through the magic of C pointers, he inserts the new element (s):
MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_CONST_PTR(rpl), VALUE, rlen);