Array#mapのメモリ確保を見る

  • ふと「Array#mapって、戻り値となる配列の要素数はレシーバの要素数と等しいな」と思った。
  • 「Array#mapはおそらくCで書いてあるだろう」
  • 「ということは、戻り値となる新たな配列はレシーバの要素数を使ってnewしているに違いない」と思った。
  • 確かめてみよう…と思ったらソースがなかった。
  • Rubyのサイトからソースを入手。
  • 展開。
  • mapをgrepする。
  • 見つけた。
static VALUE
rb_ary_collect(ary)
    VALUE ary;
{
    long i;
    VALUE collect;

    if (!rb_block_given_p()) {
        return rb_ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr);
    }

    collect = rb_ary_new2(RARRAY(ary)->len);
    for (i = 0; i < RARRAY(ary)->len; i++) {
        rb_ary_push(collect, rb_yield(RARRAY(ary)->ptr[i]));
    }
    return collect;
}
  • 予想通り。
  • ついでに、最初のif文はmap(collect)にブロックが与えられているかどうかの判定、と想像。
  • rb_ary_pushはpush, rb_yieldはyieldの役割を果たすライブラリ関数、と想像(当たり前)。