Ruby 无目标?vs.obj==零
使用Ruby 无目标?vs.obj==零,ruby,null,comparison,Ruby,Null,Comparison,使用obj.nil?或obj==nil更好吗?两者的好处是什么?就我个人而言,我更喜欢object.nil?,因为在较长的行中它可以减少混淆;但是,如果我在Rails中工作,我通常也会使用object.blank?,因为这也会检查变量是否为空。我发现自己根本没有使用.nil?,如果可以: unless obj // do work end 使用.nil?实际上速度较慢,但不明显.nil?只是一种检查对象是否等于nil的方法,除了视觉效果和所需的极少性能没有区别。可能建议使用.nil?比简单
obj.nil?
或obj==nil
更好吗?两者的好处是什么?就我个人而言,我更喜欢object.nil?
,因为在较长的行中它可以减少混淆;但是,如果我在Rails中工作,我通常也会使用object.blank?
,因为这也会检查变量是否为空。我发现自己根本没有使用.nil?
,如果可以:
unless obj
// do work
end
使用.nil?
实际上速度较慢,但不明显.nil?
只是一种检查对象是否等于nil的方法,除了视觉效果和所需的极少性能没有区别。可能建议使用.nil?比简单的比较慢,仔细想想,这是有道理的
但如果规模和速度不是你关心的,那么。零?也许更具可读性
使用obj.nil是否更好?或obj==nil
完全一样。它具有完全相同的外部可观察效应(pfff)*
两者的好处是什么
如果您喜欢微优化所有对象将返回false
到.nil?
消息,但对象nil
本身除外,而使用=
消息的对象将执行微比较
使用另一个对象来确定它是否是同一个对象
*见评论 您可以在nil?
上使用Symbol进行处理,但在x==nil
上则不实用
arr = [1, 2, 3]
arr.any?(&:nil?) # Can be done
arr.any?{|x| x == nil} # More verbose, and I suspect is slower on Ruby 1.9.2
! arr.all? # Check if any values are nil or false
在许多情况下,这两种方法都不适用,只需测试布尔真值即可
虽然这两个操作非常不同,但我很确定它们总是会产生相同的结果,至少在某个边缘的人决定覆盖对象的#nil?
方法之前是如此。(调用从对象继承或在NilClass
中重写的#nil?
方法,并与nil
单例进行比较。)
我建议,当你有疑问时,你可以走第三条路,实际上,只是测试一个表达式的真值
因此,
如果x
而不是如果x==nil
或如果x.nil?
,以便在表达式值为false时进行此测试DTRT。这样做也有助于避免诱惑他人将false类#nil?
定义为true。撇开语法和样式不谈,我想看看测试nil的各种方法是如何“相同”的。因此,我编写了一些基准测试来查看,并对其进行了各种形式的零测试
TL;DR-结果优先
实际结果表明,在所有情况下,使用obj
作为零检查是最快的obj
始终比检查obj.nil?
快30%或更多
令人惊讶的是,obj
的执行速度大约是obj==nil
上的变体的3-4倍,这似乎是一种惩罚性能的惩罚
想要将性能密集型算法的速度提高200%-300%吗?将所有obj==nil
检查转换为obj
。要对代码的性能进行沙袋处理吗?尽可能使用obj==nil
。(只是开玩笑:不要对代码进行沙袋处理!)
归根结底,始终使用obj
。这与规则不符:
基准条件
好的,这些就是结果。那么这个基准是如何组合起来的,进行了哪些测试,结果的细节是什么
我提出的零支票是:
obj
obj.nil?
!obj
!!obj
obj==nil
obj!=无
Fixnum
,Float
,false类
,TrueClass
,String
和Regex
我在每种类型上都使用了这些nil检查条件,以查看它们之间在性能方面是否存在差异。对于每种类型,我都测试了nil对象和非nil值对象(例如1_000_000
,100_000.0
,false
,true
,“string”
,以及/\w//code>),以查看在一个为零的对象上检查nil与在一个非为零的对象上检查nil是否有区别
基准
排除了所有这些,下面是基准代码:
需要“基准测试”
nil_obj=nil
N=10_000_000
把你的描述
[1_000_000,100_000.0,false,true,“string”,/\w/]。每个都有| obj|
title=“#{obj}(#{obj.class.name})”
放入“=================================================================================================================================================================================================================================================================================================================================
放置“为obj=#{title}运行测试”
Benchmark.bm(15,title)do|x|
隐式_obj_report=x.report(“obj:”){N.times{obj}
隐式报告=x.report(“nil_obj:”){N次{nil_obj}
explicit_obj_report=x.report(“obj.nil:”){N.times{obj.nil?}
explicit_nil_report=x.report(“nil_obj.nil:”){N.times{nil_obj.nil?}
not_obj_report=x.report(“!obj:”){N次{!obj}
not_nil_report=x.report(“!nil_obj:”){N次{!nil_obj}
not_not_obj_report=x.report(!!obj:){N.times{!!obj}
not_not_nil_report=x.report(!!nil_obj:){N次{!!nil_obj}
equals_obj_report=x.report(“obj==nil:”){N次{obj==nil}
等于{nil_report=x.report(“nil_obj==nil:”){N次{nil_obj==nil}}
not_等于_obj_report=x.report(“obj!=nil:”){N次{obj!=nil}
not_等于_nil_report=x.report(“nil_obj!=nil:”){N次{nil_obj!=nil}}
结束
结束
结果
结果很有趣,因为Fixnum、Float和String类型的性能实际上是i