在ruby中if(!x)vs if(x == false)

我不明白以下代码:

ruby-1.9.1-p378 > puts "nil is false" unless nil nil is false => nil ruby-1.9.1-p378 > puts "nil isn't false" unless nil == false nil isn't false => nil 

在大多数语言中(至少是C语言),if(!cond)和if(cond == false)评估相同。 是什么让这不是这样的?

(我想知道原因的细节,我明白这是怎么回事。)

Ruby认为falsenil是唯一的两个“falsy”值,而其他一切都是“truthy”。 这是根据定义,不能修改(至少在MRI中)。 这个定义用于所有内置运算符,如ifunlesswhileuntilcond ? if_truthy : if_falsey cond ? if_truthy : if_falsey||&& ,…

foo == bar将始终使用bar作为参数调用foo上的==方法。 默认情况下, nilfalsetrue和所有其他immediates,如符号等,只等于它们自己。 但是,这可以改变:

 def nil.==(bar) super || bar == false end puts "nil == false" if nil == false # => "nil == false" 

在Ruby 1.9中,您还可以重新定义运算符! ,所以unless foo不一定与if !foo相同或者与if foo相反:

 def true.! true end puts "True?" if true # => "True?" puts "or not?" if !true # => "or not?" 

不是有人会建议做这样的事情……

通过比较== nil不等于false,因为它们的语义内容不同( nil不是信息,false是布尔值)。 但是,如果您尝试在布尔上下文中评估nil ,它将被视为False,主要是为了方便和与其他语言的惯用兼容性。

nil == a <=> nil != a <=> false将是几乎任何a值的情况,除了nil。

所以你只能说’nil is not true’和’nil is nil’。 这就是ruby的方式。

在某些语言中,您只能在“if”语句中使用布尔值。 试图检查字符串或数字是真还是假是愚蠢无意义的,所以语言不会让你这样做。

然而,在Ruby中,一切都可以被认为是一个布尔值,即使它确实不是。 实际上,除了nil和false(IIRC)之外,Ruby中的所有内容都是真实的。 这并不意味着nil实际上是EQUAL为false,正如它并不意味着整数45实际上是EQUAL为true。 他们是不同的,独立的,事物。 但是如果你要像对待布尔值那样处理nil(即在if或除非中使用它)那么就好像它是假的。