动态创建的方法中的Ruby动态参数 [英] Ruby dynamic arguments in dynamically created methods

查看:58
本文介绍了动态创建的方法中的Ruby动态参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下几种方法定义:

I have the following kind of method definition:

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 慢得多. 我如何有效地对此进行存档?

So I want to get a real method. But define_method has no any possibility to define method arguments dynamically. I know another way to use class_eval but I know than defining methods with class_eval is much slower than define_method. How I can effectively archive this?

我在Rails控制台中做了一些基准测试:

I did some benchmarks in rails console:

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

所以我得到了以下结果:

So I've got the following results:

                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来实现您要的内容.由于method_body是lambda,因此它只能访问在它之前定义的局部变量.

There is no simple way to implement what you are asking using either class_eval or define_method. Since method_body is a lambda it can only access local variables defined right before it.

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:

I would suggest you to revise your requirements. If your method body should be a lambda, define all arguments for it. Then this is a natural fit for define_method:

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

如果您的方法主体可以是字符串,则eval是唯一的选择:

If your method body can be a string, eval is the only option:

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

这篇关于动态创建的方法中的Ruby动态参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆