Ruby - 检查block_given之间有什么区别?和!block.nil?

sin*_*ony 7 ruby performance ruby-block

我有一个ruby方法需要检查块是否传递给它.一位同事建议只检查block.nil?性能是否稍微快一点,并且适用于命名块.这已经非常烦人,因为他正在使用命名块并使用它来调用它block.call而不是yield显示更快,因为命名块在可读性方面更容易理解.

版本1:

def named_block &block
   if block.nil?
     puts "No block"
   else
     block.call
   end
end
Run Code Online (Sandbox Code Playgroud)

版本2:

def named_block &block
  if !block_given?
    puts "No block"
  else 
    block.call
  end
end
Run Code Online (Sandbox Code Playgroud)

基准测试显示版本1比版本2略快,但是快速查看源代码似乎表明它block_given?是线程安全的.

这两种方法有哪些主要区别?请帮我证明他错了!

ndn*_*kov 5

首先,虽然单次nil?检查的速度可能比快block_given?,但捕获块的速度却很慢。因此,除非您仍然要捕获它,否则性能参数无效。

其次,它更容易理解。每当您看到时block_given?,您便确切知道发生了什么。当您拥有时x.nil?,您必须停下来想一想x

第三,这是一个成语。以我的经验,绝大多数Ruby开发人员会更喜欢block_given?。在罗马的时候...

最后,您可以保持一致。如果您始终使用block_given?该问题,将为您解决。如果使用nil?检查,则必须捕获该块。

  • 有性能开销。
  • 它比较冗长,这是Rubyists尽量避免的。
  • 命名是编程中最困难的事情之一。:)您能想到一个好名字Enumerable#map吗?
  • “可复制性”是代码库具有的理想特征。如果要查找检查是否有障碍物的所有地方,那么检查可能会很nil?困难。

  • @ the_drow,proc是不可变的。另外我还没有检查实现,但是我猜是“ nil?”检查是原子的。因此,我认为这两种方式都不会有任何不同。 (2认同)