ruby `block_given?`是否呈现`&block`参数可选?

l7mqbcuq  于 2023-04-05  发布在  Ruby
关注(0)|答案(2)|浏览(141)

我对以下内容感到满意:

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

所以我学会了将块(和procs)与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是否由block_given?呈现为可选:

return file unless block_given?
sqyvllje

sqyvllje1#

一般来说,只有在需要将块传递给另一个方法时才使用&block参数,例如在这个虚构的例子中:

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

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

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实现一样,它们甚至可以一起使用。

31moq8wy

31moq8wy2#

方法签名中的&block接受一个块,将其转换为proc,并将其分配给名为block的变量。如果没有提供块,则将block分配给nil
是否在方法定义中使用参数block并不重要,就像在下面的定义中是否使用普通方法参数bar并不重要一样:

def foo(bar); end

然而,接受一个块作为参数而不使用它是多余的,也是浪费资源的。向其他程序员显式指示该方法接受一个块可能仍然有意义。
使用block_given?与所有这些都无关。它与是否通过&接受一个块作为参数无关。它直接引用该块,而不考虑block

相关问题