Ruby 动态定义参数

Ruby dynamically define arguments

我基本上想要实现的是:

arguments     = [:foo, :bar]
multiplicator = ->(_something_funky_with_arguments_) { foo * bar }
multiplicator.call(3, 4) # => 12

除了将整个 lambda 构建为字符串并 evaling 之外,还有其他方法吗?

eval("->(#{arguments.join(', ')}) { foo * bar }")

像这样:

multiplicator = Proc.new {|*arguments| arguments.inject(&:*) }
multiplicator.call(3, 4) # => 12
multiplicator.call(3, 4, 5) # => 60

或者如果您更喜欢 lambda 语法:

multiplicator = ->(*arguments) { arguments.inject(&:*) }
multiplicator.call(3, 4) # => 12
multiplicator.call(3, 4, 5) # => 60

评论后,也许这就是您的解决方案:

foo = 3
bar = 4
arguments     = ["foo", "bar"]
multiplicator = ->(bind) { arguments.inject(1) { |acc, var| acc * eval(var, bind)} }
multiplicator.call(binding) # => 12

在更多评论之后再尝试两次: 更简单:

require 'ostruct'
structer = OpenStruct.new
structer.foo = 3
structer.bar = 4
multiplicator = ->() { foo * bar }
structer.define_singleton_method :call_me, &multiplicator
structer.call_me # => 12

更复杂的是使用代理 class 正确设置上下文:

class Proxy
  def set_lambda(lambda_object)
    define_singleton_method :run_me, &lambda_object
    return self
  end

  def call(arg_names, *args)
    arg_names.each_with_index do |var, i|
      define_singleton_method var do args[i] end
    end
    self.run_me
  end
end
multiplicator = ->() { foo * bar }
arguments     = [:foo, :bar]
Proxy.new.set_lambda(multiplicator).call(arguments, 3, 4)

经过大量评论后,我认为这是最接近 OP 要求的评论:

class Proxy
  def set_lambda(lambda_object)
    define_singleton_method :run_me, &lambda_object
    return self
  end

  def set_arguments(args)
    @args_table = args
    return self
  end

  def call(*args)
    @args_table.each_with_index do |var, i|
      define_singleton_method var do args[i] end
    end
    self.run_me
  end
end
multiplicator = ->() { foo * bar }
arguments     = [:foo, :bar]
callable = Proxy.new.set_lambda(multiplicator).set_arguments(arguments)
callable.call(3, 4) # => 12
callable.call(4, 5) # => 20

我假设你想要动态参数

 multiplicator = ->(args) { args.inject(:*) }

 multiplicator.call([4,5,6])
 => 120