Spelunking in Ruby's Source

Ruby for Rails makes an interesting claim that object_id(), send(),
and respond_to?() are defined on Kernel. I didn’t expect this, so I
went into the source to verify and it does seem to be true in Ruby
1.8.x. These seem to be the relevant lines of eval.c:

 rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);

 rb_define_method(rb_mKernel, "send", rb_f_send, -1);
 rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);

and gc.c:

 rb_define_method(rb_mKernel, "__id__", rb_obj_id, 0);
 rb_define_method(rb_mKernel, "object_id", rb_obj_id, 0);

My first question is, why are these Kernel methods, instead of
methods on Object?

I thought Kernel was for methods like puts() that we wanted to have
globally available but that weren’t necessarily inherent to Object.
Clearly my understanding is flawed, so would someone please explain
how it is decided if a method belongs in Object or Kernel?

Fast forwarding to HEAD, this seems to have changed in Ruby 1.9.
Here are the now relevant lines of eval.c:

 rb_define_method(rb_cBasicObject, "respond_to?", obj_respond_to,

-1);

 rb_define_method(rb_cBasicObject, "send", rb_f_send, -1);
 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);

and again for gc.c:

 rb_define_method(rb_cBasicObject, "__id__", rb_obj_id, 0);
 rb_define_method(rb_cBasicObject, "object_id", rb_obj_id, 0);

Am I reading this right in that the methods have been moved to
BasicObject in Ruby 1.9?

An unrelated curiosity: while browsing the source I saw these likes
in eval.c:

 rb_define_method(rb_cBasicObject, "send", rb_f_send, -1);
 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
 rb_define_method(rb_cBasicObject, "__send", rb_f_send, -1);
 rb_define_method(rb_cBasicObject, "funcall", rb_f_funcall, -1);
 rb_define_method(rb_cBasicObject, "__send!", rb_f_funcall, -1);

Does that last one mean Matz is cracking under the pressure? :wink:

James Edward G. II

On Aug 14, 2006, at 12:53 PM, James Edward G. II wrote:

I thought Kernel was for methods like puts() that we wanted to have
globally available but that weren’t necessarily inherent to
Object. Clearly my understanding is flawed, so would someone
please explain how it is decided if a method belongs in Object or
Kernel?

Everything (almost) belongs in Kernel

% irb
irb(main):001:0> obj = Object.new
=> #Object:0x35477c
irb(main):002:0> obj.methods.map { |x| obj.method(x).inspect }.grep(/
Kernel/).size
=> 40
irb(main):003:0> obj.methods.size
=> 40

I believe the purpose of BasicObject in 1.9 is to be able to say

class O < BasicObject # I want BlankSlate without all the extra work
of undef_method
end

I don’t know anything about matz. cracking under the pressure