首页 > 解决方案 > `block_given?` 是否呈现 `&block` 参数可选?

问题描述

我对以下内容感到满意:

def some_def(foo, &block)
    puts "block utilized below"
    block.call(foo)
end

def some_other_def(bar)
    puts "using yield below"
    yield bar
    puts "and back into the method"
end

所以我学会了将块(和过程)与yield关键字分开。

但是,我遇到了以下代码:

# ./open_file.rb

class File
    def self.open(name, mode, &block)
        file = new(name, mode)
        return file unless block_given?
        yield(file)
    ensure
        file.close
    end
end

当我在 irb 中执行此代码时,参数&block似乎无关紧要:

irb -r ./file.open.rb

并执行以下操作:

File.open('foo.txt','r') {|f| puts f}

&block由 in 呈现为可选block_given?

return file unless block_given?

标签: rubyyieldruby-block

解决方案


通常,仅当您需要将块传递给另一个方法时才使用该&block参数,例如在此示例中:

def m(&block)
  some_array.map(&block)
end

Enumerable#sum或者这个来自 Rails的真实版本:

def sum(identity = nil, &block)
  if block_given?
    map(&block).sum(identity)
  else
    sum = identity ? inject(identity, :+) : inject(:+)
    sum || identity || 0
  end
end

在任何一种情况下,调用该方法的块都与另一个方法调用一起使用,因此您需要一种方法来引用该块(即名称)。

所以block_given?/yield服务&block于不同的目的。能够调用block_given?并不会造成&block冗余,并且在上面的#sum实现中,它们甚至可以一起使用。


推荐阅读