each_with_indexの実装を探す
まず、/usr/lib/ruby/1.8の中を見てみる。
% find /usr/lib/ruby/1.8 -name '*numerable*' -print
特にEnumerable.rbってファイルはない。
よく考えたら、require 'Enumerable'ってやるわけじゃなくて、include Enumerableってやってるんだった。
そもそも定義するときは、module Enumerableと書くはずなので、それを探してみる。
% grep -r 'module Enumerable' /usr/lib/ruby/1.8 /usr/lib/ruby/1.8/racc/compat.rb: module Enumerable /usr/lib/ruby/1.8/soap/property.rb: module Enumerable /usr/lib/ruby/1.8/tmail/compat.rb: module Enumerable /usr/lib/ruby/1.8/tmail/compat.rb: module Enumerable /usr/lib/ruby/1.8/tmail/compat.rb: module Enumerable /usr/lib/ruby/1.8/tmail/compat.rb: module Enumerable /usr/lib/ruby/1.8/set.rb:module Enumerable
メソッドの追加をしてるやつだけで、本体がかかってこない。
ソースコードを探してみる
% grep each_with_index *.c enum.c:each_with_index_i(val, memo) enum.c: * enum.each_with_index {|obj, i| block } -> enum enum.c: * %w(cat dog wombat).each_with_index {|item, index| enum.c:enum_each_with_index(obj) enum.c: rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&memo); enum.c: rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0);
あった。Rubyで書いてあったらテクニックを盗もうと思ったが、Cだったか。
でも、せっかくなので、該当部分(らしき所)のソースを抜き書き。
(個人的好みによりK&Rスタイルから改変)
static VALUE each_with_index_i(VALUE val,VALUE *memo){ rb_yield_values(2, val, INT2FIX(*memo)); ++*memo; return Qnil; } static VALUE enum_each_with_index(VALUE obj){ VALUE memo = 0; rb_need_block(); rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&memo); return obj; }