我无法理解此代码的逻辑:
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"
对象vf.inject(:+)
如何在此程序中调用方法each
?
each
方法如何在此程序中起作用,因为函数定义中没有提到块参数?
如果我只是致电vf.each
,为什么我会收到以下错误?
vowel_finder.rb:8:in `block in each': no block given (yield) (LocalJumpError)
from vowel_finder.rb:8:in `scan'
from vowel_finder.rb:8:in `each'
from vowel_finder.rb:13:in `<main>'
我理解的一件事是,此类中的each
方法会覆盖包含的each
模块中的Enumerable
方法。除此之外,我对each
和阻止无法理解。
有人可以向我解释逻辑及其内部工作原理吗?
答案 0 :(得分:1)
inject
方法来自Enumerable
类,该类包含在VowelFinder
中。作为inject
实施的一部分,它会调用名为each
的方法。
inject
期望被调用的对象定义了each
方法,因为Enumerable
不提供each
方法。通常,inject
在容器类的实例上调用,例如Array
和Hash
,它们根据容器设计定义each
。
因此,当vf.inject(:+)
调用each
时,它最终会调用VowelFinder#each
,正在操作的对象为vf
,而each
定义在VowelFinder
上1}}。
在Ruby中,您可以声明一个隐式接受块的方法,如each
所做的那样。从技术上讲,Ruby中的所有方法都接受一个块,但只有一些方法调用一个块。 yield
语句用于调用块。
Ruby有一个名为block_given?
的内置函数,用于检测块是否已传递给该方法。 Array
和Hash
上的许多方法都使用block_given?
来确定是调用块还是返回Enumerator
。检查block_given?
允许有条件地调用块,如下所示:
def each
if block_given?
@string.scan(/[aeiou]/) do |vowel|
yield vowel
end
else
# Do something interesting here, or better yet, return an Enumerator
end
end
在这种情况下,可以这样调用each
:
vf = VowelFinder.new("the quick brown fox jumped")
vf.each {|vowel| puts "Found the vowel: #{vowel}" }
或者这样:
vf.each
else
方法中的VowelFinder#each
留给学习练习以返回枚举器,就像惯例一样。
Enumerators and Enumerables的RubyMonk章节对此主题有很好的报道。