From: Nobuyoshi Nakada Date: 2008-02-04T16:16:08+09:00 Subject: [ruby-dev:33595] Re: performance improvement of DelegateClass (was cgi.rb再構築案) なかだです。 At Mon, 4 Feb 2008 14:27:53 +0900, Yukihiro Matsumoto wrote in [ruby-dev:33593]: > |> メソッドとして正しい識別子か調べるメソッドというものを用意したほ > |> うが簡単かも。 > | > |Symbol#inspectがクォートされているかで調べられるかなと思ったんで > |すが、:!と:!=が未対応でした。対応したほうがいいような気もします > |が、1.9で:"!".inspectした結果を1.8でevalできなくなります。どっち > |にいいですかねぇ。 > > 対応した方がよいでしょうね。コミットしてください。 どうやら、define_methodを使うのが一番速いようです。 DelegateClassは十数倍、実行性能はほぼ同じくらいです。 Index: lib/delegate.rb =================================================================== --- lib/delegate.rb (revision 15373) +++ lib/delegate.rb (working copy) @@ -144,5 +144,5 @@ class Delegator end rescue Exception - $@.delete_if{|s| /^#{__FILE__}:\d+:in `method_missing'$/ =~ s} #` + $@.delete_if{|s| %r"\A#{__FILE__}:\d+:in `method_missing'\z"o =~ s} ::Kernel::raise end @@ -247,7 +247,13 @@ end # :stopdoc: -# backward compatibility ^_^;;; -Delegater = Delegator -SimpleDelegater = SimpleDelegator +def Delegator.delegating_block(mid) + lambda do |*args, &block| + begin + @delegate_dc_obj.__send__(mid, *args, &block) + rescue + raise $!, $@[2..-1] + end + end +end # :startdoc: @@ -281,18 +287,13 @@ def DelegateClass(superclass) end } - for method in methods - begin - klass.module_eval <<-EOS, __FILE__, __LINE__+1 - def #{method}(*args, &block) - begin - @delegate_dc_obj.__send__(:#{method}, *args, &block) - rescue - raise $!, $@[2..-1] - end - end - EOS - rescue SyntaxError - raise NameError, "invalid identifier %s" % method, caller(3) + method = nil + begin + klass.module_eval do + methods.each do |mid| + define_method(mid, Delegator.delegating_block(mid)) + end end + rescue SyntaxError + raise NameError, "invalid identifier %s" % method, caller(3) end return klass -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦