Send my love to Ruby II

20 September 2007

In the last post, we saw a nice use case for the #send method. Now, we’ll see some coolness that Rubinius adds. First, some code:

1 class Apple
2   def seed
3   end
4 end
5 
6 a = Apple.new
7 
8 a.send :seed
9 a.__send__ :seed

Now, with the convenient and useful describe facility of the Rubinius compiler, we can see something interesting:


$ shotgun/rubinius describe send.rb
Path: send.rb
Size: 79 bytes

Sexp:
  [:block, 
  [:newline, 1, "(eval)", 
    [:class, [:colon2, :Apple], nil, 
      [:scope, 
        [:newline, 2, "(eval)", set_local_fp 1 ; local a

---- snip ----

pop
#line 8
push_literal 1
get_local_fp 1 ; local a
send send 1
pop
#line 9
get_local_fp 1 ; local a
push nil
push_literal 2
dup
is_symbol
git send_lbl1
send to_sym 0
send_lbl1:
push 0
set_args
send_off_stack
pop
push true
ret

---- snip ----

I’ve truncated that output, but feel free to run this at home. (There’s no long lasting side effects other than an itching desire to contribute to the Rubinius project.) If you correlate the assembly with the line numbers in the source, you’ll notice that the two sends are not turning out to be the same. That’s right. We have a special, and fast, __send__ operation.

The #send method is a highly useful bit of Ruby. Unfortunately, there’s some concern that using it can hurt performance. Well, with Rubinius you can have your send and use it, too.