在Ruby中将方法作为参数传递怎么做?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (33)

我试图用Ruby来解决一些问题。因此,我尝试从“Programming Collective Intelligence”Ruby这本书中实现算法(Python中给出的)。

在第8章中,作者将一个方法a作为参数传递。这似乎在Python中工作,但不在Ruby中。

我在这里有这个方法

def gaussian(dist, sigma=10.0)
  foo
end

并想用另一种方法调用此方法

def weightedknn(data, vec1, k = 5, weightf = gaussian)
  foo
  weight = weightf(dist)
  foo
end

我得到的只是一个错误

ArgumentError: wrong number of arguments (0 for 1)
提问于
用户回答回答于

你需要一个proc对象:

gaussian = Proc.new do |dist, *args|
  sigma = args.first || 10.0
  ...
end

def weightedknn(data, vec1, k = 5, weightf = gaussian)
  ...
  weight = weightf.call(dist)
  ...
end

请注意,不能像这样在块声明中设置默认参数。所以需要使用splat并在proc代码中设置默认值。

或者,根据所有这些的范围,可能会更容易传递方法名称。

def weightedknn(data, vec1, k = 5, weightf = :gaussian)
  ...
  weight = self.send(weightf)
  ...
end

在这种情况下,只需调用一个在对象上定义的方法,而不是传入完整的代码块。这取决于你如何组织这个你可能需要更换self.sendobject_that_has_the_these_math_methods.send

最后但并非最不重要的是,可以挂掉方法。

def weightedknn(data, vec1, k = 5)
  ...
  weight = 
    if block_given?
      yield(dist)
    else
      gaussian.call(dist)
    end
  end
  ...
end

weightedknn(foo, bar) do |dist|
  # square the dist
  dist * dist
end

但是这听起来像你想在这里更多的可重用的代码块。

用户回答回答于

引用块和Proc的注释是正确的,因为它们在Ruby中更常见。但是如果你愿意,你可以传递一个方法。调用method来获取方法并.call调用它:

def weightedknn( data, vec1, k = 5, weightf = method(:gaussian) )
  ...
  weight = weightf.call( dist )
  ...
end

扫码关注云+社区