У меня есть следующий вид определения метода:Рубиновые динамические аргументы в динамически создаваемых методах
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)
'class_eval' имеет смысл для меня. Является ли производительность действительно проблемой? Трудно представить себе, где это будет. –
Возможно, ваш блок define_method принимает varargs, а затем интерпретирует массив args на основе ваших метаданных аргументов, захваченных в закрытии. – dbenhur
@dbenhur, нормально, но в этом случае на самом деле у меня есть один метод, который реализует многополярное поведение, поэтому я должен реализовывать поведение основных аргументов вручную (присутствие аргументов, аргументы по умолчанию и т. Д.). Это то, чего я пытаюсь избежать. – freemanoid