Ruby hack Challenge もくもく会 に参加してきました

connpass.com

一言感想。コミッターの方が多数いてすげーなーという気持ちになりました


えーとこの会自体は Ruby hack Challenge という企画のもくもく会です。
企画自体はこちらのレポを参照するのがよいかと。

codeiq.jp

僕は rhc 自体には参加してないのですが RubyKaigi 以降はよく ruby/ruby を眺めているのでいってきました。

もくもく会なのでみんな適当になんかする、という感じだったのですが、僕はあまり何をするか考えていませんでした。とりあえずruby/rubyよんで気になったとこを見ようかなという気持ちです。
特に目的も定めずにざーっと読んで読んで、読み進めて。
気になったのが array.c の Array#uniq! の実装。frozen チェックのあたりがちょっと気になります。

static VALUE
rb_ary_uniq_bang(VALUE ary)
{
    VALUE hash;
    long hash_size;

    rb_ary_modify_check(ary);
    if (RARRAY_LEN(ary) <= 1)
        return Qnil;
    if (rb_block_given_p())
        hash = ary_make_hash_by(ary);
    else
        hash = ary_make_hash(ary);

    hash_size = RHASH_SIZE(hash);
    if (RARRAY_LEN(ary) == hash_size) {
    return Qnil;
    }
    rb_ary_modify_check(ary);
    / * ary を削ってからいれるような処理 */
}

rb_ary_modify_check は freeze 状態だったら例外を投げる的なやつです。
でも関数の最初のほうで rb_ary_modify_check をしているのにもう1回やってます。どういう理由でしょう。

最初に読んだときは「マルチスレッド対応かな?」と思っていたのですが、質問してみるとそうではないとのこと1
それより rb_block_given_p が truthy のときではないかとアドバイスを受けました。
RubyArray#uniq! はブロックをとると、その評価値をもとに uniq をしてくれる仕様です。このブロック評価時に freeze させた場合のためのチェックのようですね。
blame してみるとたしかにそういったコミットがひっかかります。

github.com

そんでなんやかんやしてたらすぐに時間がきて終了。パッチは作ったものの、既存の動作を変更するのでどうしたもんかなーと悩み中です2
できたらパッチ送りたかったけど送れず……。次回はもう少し先にアタリをつけておいてすすめたいですね。
次回が来月にあるということなので次回はパッチ投げるところまですすみたいものです


  1. なんでそうではないんだか忘れたんだけどGVLがある中で、(ブロック評価とかを除いて)Cの関数実行中にコンテキストスイッチが入らないみたいな話だった気がする……

  2. まだ悩んでる