屈服于块

你可以向你的方法发送一个块,它可以多次调用该块。这可以通过发送 proc / lambda 等来完成,但是使用 yield 更容易,更快:

def simple(arg1,arg2)
  puts "First we are here:  #{arg1}"
  yield
  puts "Finally we are here:  #{arg2}"
  yield
end
simple('start','end') { puts "Now we are inside the yield" }

#> First we are here:  start
#> Now we are inside the yield
#> Finally we are here:  end
#> Now we are inside the yield

请注意,{ puts ... } 不在括号内,它隐含在后面。这也意味着我们只能拥有一个 yield 块。我们可以将参数传递给 yield

def simple(arg)
  puts "Before yield"
  yield(arg)
  puts "After yield"
end
simple('Dave') { |name| puts "My name is #{name}" }

#> Before yield
#> My name is Dave
#> After yield

有了 yield,我们可以轻松地创建迭代器或任何适用于其他代码的函数:

def countdown(num)
  num.times do |i|
    yield(num-i)
  end
end

countdown(5) { |i| puts "Call number #{i}" }

#> Call number 5
#> Call number 4
#> Call number 3
#> Call number 2
#> Call number 1

事实上,foreacheachtimes 这样的东西通常都是在课堂上实现的。

如果你想知道你是否被阻止,请使用 block_given?

class Employees
  def names
    ret = []
    @employees.each do |emp|
      if block_given?
        yield(emp.name)
      else
        ret.push(emp.name) 
      end
    end

    ret
  end
end

此示例假定 Employees 类具有 @employees 列表,可以使用 each 迭代以使用 name 方法获取具有员工姓名的对象。如果给出一个块,那么我们将把该名称改为块,否则我们只是将它推送到我们返回的数组。