【发布时间】:2013-03-29 21:39:11
【问题描述】:
我有以下几种方法定义:
method_name = :foo
method_arguments = [:bar, :baz]
method_mandatory_arguments = {:quux => true}
method_body = ->{ quux ? bar + baz : bar - baz }
所以我想得到一个真正的方法。但是define_method 不可能动态定义方法参数。我知道使用class_eval 的另一种方法,但我知道使用class_eval 定义方法比define_method 慢得多。 我怎样才能有效地归档这个?
我在 rails 控制台做了一些基准测试:
class Foo; end
n = 100_000
Benchmark.bm do |x|
x.report('define_method') do
n.times { |i| Foo.send(:define_method, "method1#{i}", Proc.new { |a, b, c| a + b + c }) }
end
x.report('class_eval') do
n.times { |i| Foo.class_eval %Q{ def method2#{i}(a, b, c); a + b + c; end } }
end
end
所以我得到了以下结果:
user system total real
define_method 0.750000 0.040000 0.790000 ( 0.782988)
class_eval 9.510000 0.070000 9.580000 ( 9.580577)
【问题讨论】:
-
class_eval对我来说很有意义。性能真的是这里的问题吗?很难想象它会有一个用例。 -
您可以让您的 define_method 块接受可变参数,然后根据您在闭包中捕获的参数元数据解释 args 数组。
-
@dbenhur,好的,但在这种情况下,实际上我有一种实现乘法行为的方法,所以我必须手动实现基本的参数行为(参数存在、默认参数等)。这是我试图避免的。
-
你确定 class_eval 对这类东西比较慢吗?我的回忆是因为 define_method 创建了一个闭包,它可能会更慢(或导致泄漏)
-
鉴于 method_body 是一个没有参数的 lambda,您能否向我们展示您使用 class_eval 的实现?
标签: ruby dynamic metaprogramming dynamic-programming