2

鉴于此代码:

a = {1=>2}
m = a.method(:[])

我知道我现在可以使用:

value = m.call(1)

它会返回 2。问题是,我需要更改什么才能直接调用该方法,例如:

m.call()

它会将 1 作为参数发送?能够写出类似的东西会很好:

m = a.method(:[],1) # where the symbol is the method, and 1 will be the parameter it will be called with

问题是,我想延迟执行我的脚本的某些部分,直到创建一些对象,并且我想避免重写一切以使用 lambdas。

4

3 回答 3

3

我敢肯定,有不止一种方法可以做到这一点。

a = {1=>2}

class << a
  def fetch_what(key)
    Proc.new { self[key] }
  end
end

....

m = a.fetch_what(1)
m.call()  # -> 2
于 2009-11-10T14:20:39.337 回答
3

基本上,你想要的是一种对函数进行柯里化的方法。

http://en.wikipedia.org/wiki/Curry_function

这可以通过许多不同的方式完成,其中之一:

def curry(method, *params)
  lambda { send method, *params }
end

您可以将其添加到 Hash 的元类中,或者添加到要包含在某些对象中的模块中,等等。然后,调用它成为您想要的用例:

irb(main):001:0> a = {1 => 2}
=> {1=>2}
... # add curry to Hash's metaclass
irb(main):011:0> m = a.curry :[], 1
=> #<Proc:0xb76e2154@(irb):8>
irb(main):012:0> m.call
=> 2
于 2009-11-10T16:53:33.693 回答
0

听起来您应该将方法参数附加到您正在调用该方法的对象上,并让该方法将它们作为实例变量进行访问。

就简单的重构步骤而言:

  • 引入新的实例变量,每个方法参数一个。
  • 为实例变量引入新的访问器。
  • 如果未提供参数,请重构方法以使用实例变量。
  • 在方法调用之前的某个时刻,重构调用代码以通过访问器设置实例变量。
  • 重构调用代码以在方法调用中不传递任何参数。

例如,重构调用代码如下:

widget = Widget.new
assembly_method = widget.method(:assemble)
# Time passes...
assembly_method.call(:electric, :smooth)

像这样工作:

widget = Widget.new
widget.frombulator = :electric
widget.jazzifier = :smooth
assembly_method = widget.method(:assemble)
# Time passes...
assembly_method.call

它既不性感也不聪明,但它会产生表达其意图的代码,并且很有可能它会解决真正的问题,即你的模型中缺少某些东西。

于 2009-11-10T16:09:38.807 回答