1

这是 ruby​​ pickaxe book 中的代码示例:

Class VowelFinder
  include Enumerable

  def initialize(string)
    @string = string
  end

  def each
    @string.scan(/[aeiou]/] do |vowel|
      yield vowel
    end
  end
end

vf = VowelFinder.new("the quick brown fox jumped")    
vf.inject(:+)        # => 'euiooue'

我很难理解的是修改后的“每个”方法在哪里发挥作用?我假设 inject 在某个时候调用它,但不明白它为什么这样做,以及我如何在我的代码中预测或模拟这种行为。

谢谢!

4

3 回答 3

1

该类VowelFinder实现了模块所必需的协议Enumerable,您可以包含该协议以获得大量 ruby​​ 迭代器方法:http ://apidock.com/ruby/Enumerable

Enumerable mixin 为集合类提供了几种遍历和搜索方法,以及排序的能力。每个类必须提供一个方法,该方法产生集合的连续成员。如果使用 Enumerable#max、#min 或 #sort,则集合中的对象还必须实现有意义的 <=> 运算符,因为这些方法依赖于集合成员之间的排序。

于 2012-08-06T14:09:30.293 回答
1

调用inject实际上会导致调用each。工作方式inject是遍历Enumerableusing的所有元素each,将传递的运算符应用于memo下一个值并将结果存储回memo. 整个调用的结果是最后的值memo您可以在此处查看文档。

于 2012-08-06T14:03:27.613 回答
1

你是正确的,注入实际上调用了每个方法,发生这种情况的原因是因为注入实际上在内部使用了每个方法。事实上,很多如果 Enumerable 方法使用 .each 方法;比如#map、#select、#reject。

这样做的原因是 .each 是允许在 Enumerable Object 中循环的实际方法。其他方法只是为了让我们,开发人员的事情变得容易,我们不必在任何地方使用 .each 。想象一下,必须使用 .each 编写上述代码。这并不难,但 vf.inject(:+) 绝对更容易。collect 或 map 的情况也是如此。

实现这一点(如在 Ruby 中所做的那样)而不重复代码的最佳方法是让另一个方法调用 #each,因为没有代码重复,并且每个 #map 或 #collect 或 #inject 都不必遍历 Enumerable对象不同。

一般来说,我避免使用#each,还有很多其他方法可以让我们的工作更轻松。如果你想修改你的数组集合,建议不要给 #each 方法打补丁(当然,除非你希望所有其他方法也改变。)

于 2012-08-06T14:29:00.127 回答