Bignumは遅いとのことで測った

10週遅れぐらいでRHGを読み始めた。

第二章の整数の説明でFixnumとBignumの内部実装の違いについて書いてある。

Rubyのオブジェクトは基本的には各々のクラスの構造体へのポインタ(RBasic.klass)を持つんだけど、効率面を考えて一部のオブジェクト*1はこのポインタ変数の領域に構造体へのポインタではなく即値を書くようにしている。Fixnumもこの場合に当てはまる。

なんで、ポインタ型のサイズにいい感じに収まる範囲ならFixnum、サイズを超える場合はBignumに勝手に切り替わる。

(正確には sizeof(unsigned long)*8-1ビットの範囲に収まる符号付き整数)

Bignumはクラス構造体を作ってポインタを持つので生成コストが高い。

最近のRubyでもそうなのかなと思って測った。

gistde49f43915b2ca6d5ae8

原因がRHGが書かれた時点のRubyと同じかはわからないけど遅かった。

*1:RHGが書かれた時点のRubyでは小さな整数、シンボル、true、false、nil、Qundef

熱海に行って画像に文字をいれるためのコードを書いていた

f:id:kouba_c:20140511230451p:plain

土日、友人に誘われて熱海で開発合宿もどきのようなものをやってきた。

開催が決まったの金曜深夜だったので完全に行き当たりばったりの企画で、 特に何を作るとか考えていなかったので画像に文字をいれるgemを作っていた。

Github - Tym

このgemを使うことで簡単にマリオのエンディングっぽい画像を量産できるようになった。

学び

  • ImageMagickRubyインタフェースであるRMagickを少し使えるようになった
    • 微妙にインタフェースが使いづらい気がする、誰か代替品作っていないのか
  • DSLパース処理書いて少し正規表現力が上がった
    • DSLの文法凝りたい
  • RSpecでそれなりにテスト書いた

開発合宿もどき

プライベートで知り合いと同じ空間でコード書くのはじめてだったけど、監視されてる感と優越感ゲームに勝ちたい感が相まって、自宅よりもかなり集中して長時間コーディングできた。

ぜひまた行きたい。

熱海

東京からだとかなり気楽に行けるしそこまで交通費もかからない。

街の印象としては温泉と秘宝館のある長崎みたいだった。

git hooksでMilkodeとctagsを自動的に設定

Milkode

最近Milkodeというソースコード検索ツールを使ってる。
Rubyで書かれてるし早いっぽいしお気に入り。
Milkode - 行指向のソースコード検索エンジン

git hooksで自動更新

githubからcloneしたコードは基本的にmilkodeに登録したいので、git hooks使ってclone時に追加/pull時に更新したい。

git hooks置き場

template directoryに置いておくことで、新しいgitリポジトリ生成時に勝手にコピーしてくれる。
template directoryの探索順は以下参照。
git-init(1)
デフォルトの/usr/share/git-core/templatesは触りたくないので以下を実行。

$ mkdir -p ~/.git_template/hooks
$ git config --global init.templatedir '~/.git_template' #hooksはつけない

これで~/.git_template以下に置いたhookスクリプトが使われる。

使うgit hooks

git help hooksにいろいろ書いてある。
man page githooks section 5
post-checkoutでclone(ついでにブランチ切り替え)、post-mergeでpullをフックできるっぽい。
~/.git_templateに以下を置いて実行権限つけておく。

~/.git_template/hooks/post-checkout
echo "[hook]milkode add"
milk add .
~/.git_template/hooks/post-merge
echo "[hook]milkode update"
milk update

これで動作する感じ。
ただ、フックのタイミング完全に把握してないので意図しないタイミングで動作する可能性があるし、意図しないリポジトリ(NeoBundleで入れたプラグインとか)も登録される。
工夫すれば解決できると思う。

ctagsも更新

ctagsの生成はvim pluginのvim-tagsでやっている。
https://github.com/szw/vim-tags
タグの生成にはvim上で:TagsGenerateコマンドを実行する必要があるんだけど、git clone後にいちいちvim開きたくないのでこれもgit hooksで更新したい。
vim自体は開かずにvimのコマンドを実行するには起動プションに -c を駆使すればできるっぽい。
Vim documentation: starting

vim -c TagsGenerate -c q

ただし"Vim: Warning: Input is not from a terminal"という警告が出てしまう。
vimの標準入力がターミナルからの入力以外だと出るとのこと、フックスクリプトがどう実行されているのかわからないのでとりあえず放置。
気になるようなら普通に

ctags -R -f .git/tags

あたりを書いておけばいい気がする。

参考にさせていただいた記事

http://qiita.com/quattro_4/items/59fdf8b9aa9ef48ecbdf/

渡されたblockを回数制限付きで例外retry

例外あがってきたときに回数制限つきで retry するのどうやったらきれいに書けるの問題 in ruby - life.should be_happy # => 1 examples, ? failures
を見て。
なれないProc使ってるせいでださい、もっともっとかっこよく書けるはず。

メソッドのsender/receiver入れ替え

脳が疲れているとメソッドの呼び出し元を間違えて

1.include?([1,2,3,4,5])

みたいなコードを書いてしまうことがあるので、以下のようなコードを考えた。

当然、sender/receiverどちらにもないメソッドを呼ぶと無限にスタックを積み上げて落ちる。
コールスタックを読んで、過去に自身のmethod_missingが呼ばれていれば例外にすればいい気がしたが、Kernel.#callerでは呼び出し元オブジェクトを特定する情報が無かった。
過去にActiveSupportにBinding.of_callerというものがあったらしいがRubyのバグを利用した黒魔術によって実現されており1.8.5から使えなくなったとか。
Kernel.#set_trace_funcでbindingオブジェクト取れるのでなんとかなりそうな気もしたけど面倒くさすぎるので諦めた。

https://github.com/banister/binding_of_caller
こういうgemもあった(試してない)

オブジェクトにあとからインスタンス変数を追加

どうしようもないコードとどうしようもないコードを無理やりつなげ合わせなきゃいけない時に。
Objectクラスのinstance_variable_setでもできるけどgetter/setterが必要だったので。

succメソッドの使い方

定義したオブジェクトをRangeで使えるようにするにはsuccメソッドと<=>メソッドを定義する必要があるそうです。
いろんなオブジェクトをいろんな増加値で範囲オブジェクトにしたいコード。