检查块是否有区别
我有一个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?
检查,你必须捕获块。
Enumerable#map
会得到一个好名字吗? 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?