如何将函数作为方法参数传递

时间:2015-09-17 04:41:31

标签: ruby metaprogramming

我试图将函数作为参数传递给类的方法。我知道我需要使用proc,但我不确定我使用的是正确的语法。这是我的尝试。

module MyApp;end
module MyApp::Stats
  def self.sum(a)
    a.inject(0){ |accum, i| accum + i }
  end

  def self.mean(a)
    sum(a) / a.length.to_f
  end
  # Many more functions....      

  def self.sum_proc
    Proc.new{|x| sum(x) }
  end

  def self.mean_proc
    Proc.new{|x| mean(x)}
  end
  # And many more procs

end

class MyData
  attr_reader :values
  attr_reader :aggregates

  def initialize(array)
    @values = array
    @aggregates = {}
  end

  def aggregate(aggregator)
    puts aggregator.call(@values)
    #I would also like to create a hash of aggregator. Something like:
    #aggregates["aggregator"] = aggregator.call(@values) 
  end

end

我可以做

ar = [1,2,3,4,5,6,7,8,9]
data = MyData.new(ar)

以各种方式调用aggregate方法:

aggregator = Proc.new{|x| MyApp::Stats.sum(x)}
data.aggregate(aggregator)

data.aggregate(Proc.new{|x| MyApp::Stats.mean(x)} )

data.aggregate(Proc.new{|x| x.count{|y| y > 3.0} })

data.aggregate(MyApp::Stats.sum_proc)

data.aggregate(MyApp::Stats.mean_proc)

我对此代码有两个问题。首先,它似乎是多余的,因为我必须首先定义聚合器,然后是相关的proc,例如sumsum_proc。其次,我想知道如何在不为其定义过程的情况下传递任何标准enumerator方法:说countfirst

最后,我想为聚合器创建一个哈希,以便我可以这样做:

puts data.aggregates["sum"]
puts data.aggregates["mean"]

1 个答案:

答案 0 :(得分:2)

方法不是Ruby中的对象。您不能将方法作为参数传递,因为您只能将对象作为参数传递。

但是,您可以通过调用method方法并将方法的名称作为参数传递来获取表示方法的Method代理对象。 Proc代理对象为duck-type arity,因此他们会回复parametersto_proc,最重要的是calldef aggregate yield @values end

单个第一类程序作为参数的惯用方法是采用这样的块:

&

并使用一元前缀data.aggregate(&MyApp::Stats.method(:sum)) 运算符传递方法:

## Linux
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0  35268 117568 158244 1849104    0    0     3 11321    5    2  9 15 73  3  0