在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认为false
和nil
是唯一的两个“falsy”值,而其他一切都是“truthy”。 这是根据定义,不能修改(至少在MRI中)。 这个定义用于所有内置运算符,如if
, unless
, while
, until
, cond ? if_truthy : if_falsey
cond ? if_truthy : if_falsey
, ||
, &&
,…
写foo == bar
将始终使用bar
作为参数调用foo
上的==
方法。 默认情况下, nil
, false
, true
和所有其他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或除非中使用它)那么就好像它是假的。