如何"每个"和"注入(符号)"方法适用于以下代码?

时间:2016-05-18 14:30:07

标签: ruby iteration symbols

我无法理解此代码的逻辑:

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"
  1. 对象vf.inject(:+)如何在此程序中调用方法each

  2. each方法如何在此程序中起作用,因为函数定义中没有提到块参数?

  3. 如果我只是致电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>'
    
  4. 我理解的一件事是,此类中的each方法会覆盖包含的each模块中的Enumerable方法。除此之外,我对each和阻止无法理解。

    有人可以向我解释逻辑及其内部工作原理吗?

1 个答案:

答案 0 :(得分:1)

inject方法来自Enumerable类,该类包含在VowelFinder中。作为inject实施的一部分,它会调用名为each的方法。

inject期望被调用的对象定义了each方法,因为Enumerable 提供each方法。通常,inject在容器类的实例上调用,例如ArrayHash,它们根据容器设计定义each

因此,当vf.inject(:+)调用each时,它最终会调用VowelFinder#each,正在操作的对象为vf,而each定义在VowelFinder上1}}。

在Ruby中,您可以声明一个隐式接受块的方法,如each所做的那样。从技术上讲,Ruby中的所有方法都接受一个块,但只有一些方法调用一个块。 yield语句用于调用块。

Ruby有一个名为block_given?的内置函数,用于检测块是否已传递给该方法。 ArrayHash上的许多方法都使用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 EnumerablesRubyMonk章节对此主题有很好的报道。