Ruby “each”方法何时以及如何工作?

Ruby “each”方法何时以及如何工作?,ruby,Ruby,我不明白为什么此代码中定义了每个方法: 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")

我不明白为什么此代码中定义了
每个
方法:

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"
此代码可以工作,但不能没有
每个
。另外,如果我使用
Array
Range
类,并覆盖其中的
每个方法,则会发生不同的情况


当我创建一个对象,并对其调用
inject
方法时,
每个
方法何时以及如何工作?

TL:DR可枚举的mixin通过一种与您签订的合同工作。你告诉它每一个
都意味着什么,它就带来了几十种额外的方法
inject
是这些方法之一

实际讨论
inject
是如何工作的?粗略地说,它遍历由元素组成的对象,在元素到达时对其应用函数。字符串的元素是什么?
“快速棕色狐狸跳跃”
?可以说,它们是它的特征。因此,如果我们将字符串视为一个字符数组,并注入连接字符串的
+
,我们希望得到原始字符串本身:

arr = "The quick brown fox jumped".scan /./
puts arr.inject(:+) # => the quick brown fox jumped
但现在让我们更进一步。Ruby有mixin,特别是它有可枚举的mixin。这使我们能够将我们喜欢的任何东西视为“有元素的东西”。因此,我们可以在字符串本身的元素上注入
+
,而不是数组。为此,我们必须为一个字符串定义
每个
,这样就可以遍历字符串的元素。一旦我们做到了这一点,Enumerable的许多方法,包括
inject
,将焕然一新

对于字符串,
每个
应该意味着什么?同样,我们可以简单地让它代表每个角色。可以想象,我们可以将
每个
别名为现有的
每个字符

class String
  include Enumerable
  alias each each_char
end
s = "the quick brown fox jumped"
puts s.inject(:+) # => the quick brown fox jumped
但是,我们可以从头开始定义
每一个
,而不是将
每一个
别名为
每一个字符
。我们已经知道了一种方法,即使用
scan

class String
  include Enumerable
  def each
    self.scan(/./) do |ch|
      yield ch
    end
  end
end
s = "the quick brown fox jumped"
puts s.inject(:+) # => the quick brown fox jumped
但是每个
的定义取决于我,所以我可以扫描其他模式,而不是扫描每个字符!例如,我可以扫描元音:

class String
  include Enumerable
  def each
    self.scan(/[aeiou]/) do |ch|
      yield ch
    end
  end
end
s = "the quick brown fox jumped"
puts s.inject(:+) # => euiooue

但我们不要用这种奇怪的方式定义
每一个
,让字符串变得支离破碎。让我们把整个功能都放到一个自定义类上。让我们称之为元音提示!因此,我们以您开始使用的代码结束。

是一个很好的解释。它可以工作,兄弟@Matt作者已将
可枚举
包含在自定义类
元音索引
中。为了能够使用
Enumerable
的许多优秀实例方法,该类必须有一个实例方法
每个
都返回一个枚举数。所有的
Enumerable
实例方法都需要一个枚举数作为它们的接收者。@CarySwoveland就像上面说的:
Enumerable
mixin为集合类提供了多种遍历和搜索方法,并具有排序功能。类必须为每个
提供一个方法,该方法生成集合的连续成员。“@muistooshort实际上不需要包含
枚举数
,只要创建
枚举数
枚举器
类已经有了一个
每个
方法,并且包括
可枚举的
。在这种情况下,可以使用
Kernel#to#u enum
/
#enum#u for
,例如
“快速棕色狐狸跳跃”。enum#u for(:scan,/[aeiou]/)。inject(:+)#=>“euiooue”
。这将使用参数
/[aeiou]/
String#scan
创建一个
枚举器
,当调用inject时,每个元音都将产生到
Symbol#to_proc
提供的块。