在动态创建的方法Ruby的动态参数(Ruby dynamic arguments in dynami

2019-08-20 04:45发布

我有以下样的方法定义的:

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 。 我如何能有效的归档吗?

我没有在轨控制台一些基准:

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)

Answer 1:

还有就是要实现您正在使用class_eval或define_method问什么没有简单的方法。 由于method_body是一个lambda它只能访问前右它定义局部变量。

method_body = ->{ quux ? bar + baz : bar - baz }
quux = true
method_body.call # undefined local variable or method ‘quux’

quux = true
method_body = ->{ quux ? bar + baz : bar - baz }
method_body.call # undefined local variable or method ‘bar’

我建议你修改你的要求。 如果你的方法体应该是一个lambda,定义所有的参数吧。 那么这是一个天作之合define_method:

method_body = ->(quux, bar = 0, baz = 0){ quux ? bar + baz : bar - baz }
define_method(method_name, &method_body)

如果你的方法体可以是一个字符串,EVAL是唯一的选择:

method_body = "quux ? bar + baz : bar - baz"
eval <<RUBY
def #{method_name} #{arguments}
  #{method_body}
end
RUBY


文章来源: Ruby dynamic arguments in dynamically created methods