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
提供的块。