From: Trans Date: 2005-08-30T23:56:24+09:00 Subject: Re: Method behaves differently when called using #send Yukihiro Matsumoto wrote: > Hi, > > In message "Re: Method behaves differently when called using #send" > on Tue, 30 Aug 2005 14:36:24 +0900, "Trans" writes: > > |At first glance that seems amazingly logical. But on second thought it > |may be too logical. What of the use case where one purposefuly wishes > |to call private method from the outside (you know "bad-form" > |meta-programming stuff). > > foo.instance_eval{ > send(:bar) > } Matz, this whole thing of "protecting the programmer" via name games and block scopes, is a weak solution. Yes, I know some people love it; it seems so clever. But really, what does it accomplish other than making us type more and slowing down programs? Is it supposed to discourage us from doing it? Then why allow us to do it in the first place? It gets to be rather silly. Fifteen more characters: "foo.send(:bar)".size #=> 14 "foo.instance_eval{send(:bar)}".size #=> 29 Twice as slow: CURRENT user system total real normal : 0.040000 0.010000 0.050000 ( 0.102307) send_symbol : 0.050000 0.010000 0.060000 ( 0.110930) send_string : 0.080000 0.010000 0.090000 ( 0.134324) bind : 0.090000 0.020000 0.110000 ( 0.168328) instance_eval : 0.120000 0.020000 0.140000 ( 0.186177) inst_eval_send* : 0.120000 0.020000 0.140000 ( 0.207331) by_eval : 0.270000 0.020000 0.290000 ( 0.342002) -- b_call.rb -------------------------------------------------- # Some speed comparisions between ways to call a method. require 'benchmark' $n = 50000 # standard array def callme ; 1 ; end $m = self.class.instance_method(:callme) def call_normal $n.times do callme end end def call_by_send_symbol $n.times do send(:callme) end end def call_by_send_string $n.times do send("callme") end end def call_by_eval $n.times do eval "callme" end end def call_by_instance_eval $n.times do instance_eval { callme } end end def call_by_bind $n.times do $m.bind(self).call end end def call_inst_eval_send $n.times do $m.instance_eval { send(:callme) } end end ### --- bench --- puts "\nCURRENT" Benchmark.bm(15) do |b| b.report("normal :") { call_normal } b.report("send_symbol :") { call_by_send_symbol } b.report("send_string :") { call_by_send_string } b.report("bind :") { call_by_bind } b.report("instance_eval :") { call_by_instance_eval } b.report("*inst_eval_send :") { call_inst_eval_send } b.report("by_eval :") { call_by_eval } end