检查块是否有区别

我有一个ruby方法需要检查一个块是否传递给它。 一位同事建议简单地检查block.nil? 性能略快,适用于命名模块。 这已经很烦人了,因为他使用的是命名块并使用block.call调用它,而不是显示速度更快的yield ,因为命名块在可读性方面更容易理解。

版本1:

def named_block &block
   if block.nil?
     puts "No block"
   else
     block.call
   end
end

版本2:

def named_block &block
  if !block_given?
    puts "No block"
  else 
    block.call
  end
end

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

这两种方法的主要区别是什么? 请帮我证明他错了!


首先,一个nil? 检查可能比block_given?更快block_given? ,捕获块很慢。 所以,除非你打算捕捉它,否则表演的说法是无效的。

其次,它更容易理解。 每当你看到block_given? ,你知道到底是什么。 当你有x.nil? ,你必须停下来思考x是什么。

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

最后,你可以保持一致。 如果你总是使用block_given? 问题解决了你。 如果你使用nil? 检查,你必须捕获块。

  • 有一个性能开销。
  • 它更冗长,Rubyists试图避免的东西。
  • 命名事物是编程中最难的事情之一。 :)你能想到Enumerable#map会得到一个好名字吗?
  • “Grepability”对于代码库来说是一个理想的特性。 如果你想找到所有的地方,你检查你是否得到一个街区,做nil? 检查可能很困难。

  • 我认为主要区别是block_given? 可以在不明确定义方法定义中的&block情况下使用:

    def named_block
      if !block_given?
        puts "No block"
      else 
        yield
      end
    end
    

    为了可读性,哪个版本更好? 有时,明确命名块可以更易读,有时yield可以更易读。 这也是个人喜好的主要因素。

    当它进入速度时,在基准测试中,你已经包括在内, yield更快。 这是因为Ruby doesen不必为该块初始化新对象( Proc )并将其分配给变量。


    还有另一种方法可以实现这一点:

    def named_block
       (Proc.new rescue puts("No block") || ->{}).call
    end
    
    ▶ named_block
    #⇒ No block
    ▶ named_block { puts 'BLOCK!' }
    #⇒ BLOCK!
    

    请不要太认真

    UPD :正如@Lukas在评论中指出的那样,它在块上失败,引发异常⇒固定

    链接地址: http://www.djcxy.com/p/37225.html

    上一篇: What are the differences between checking if block

    下一篇: Why is there a difference between Java8 and Scala2.12 lambda cache?