只是想知道Ruby中的!!
是什么。
答案 0 :(得分:154)
不是。它用于将值转换为布尔值:
!!nil #=> false
!!"abc" #=> true
!!false #=> false
通常没有必要使用,因为Ruby的唯一错误值是nil
和false
,所以通常最好让这个约定成立。
将其视为
!(!some_val)
合法使用的一件事是防止返回大量数据。例如,您可能不希望在has_image?
方法中返回3MB的图像数据,或者您可能不希望在logged_in?
方法中返回整个用户对象。使用!!
将这些对象转换为简单的true
/ false
。
答案 1 :(得分:29)
如果右侧的对象不是true
而不是nil
,false
,如果它是false
或nil
,则返回false
def logged_in?
!!@current_user
end
答案 2 :(得分:14)
!
表示否定布尔状态,除了双重否定之外,两个!
s没什么特别的。
!true == false
# => true
它通常用于强制方法返回布尔值。它将检测任何类型的真实性,例如字符串,整数和不是什么,并将其转换为布尔值。
!"wtf"
# => false
!!"wtf"
# => true
更真实的用例:
def title
"I return a string."
end
def title_exists?
!!title
end
当您想确保返回布尔值时,这非常有用。但是,恕我直言,看到if 'some string'
和if true
都是完全相同的流,但有些人发现显式返回布尔值很有用。
答案 3 :(得分:6)
请注意,这个习语也存在于其他编程语言中。 C没有固有bool
类型,因此所有布尔值都被输入为int
,而标准值为0
或1
。采用这个例子(为了清楚起见,添加了括号):
!(1234) == 0
!(0) == 1
!(!(1234)) == 1
“not-not”语法将任何非零整数转换为1
,即规范布尔值。
但总的来说,我发现进行合理的比较比使用这种不常见的习语要好得多:
int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
答案 4 :(得分:3)
如果你需要exclusive or,这很有用。复制Matt Van Horn的答案略有修改:
1 ^ true
TypeError: can't convert true into Integer
!!1 ^ !!true
=> false
我用它来确保两个变量都是零,或两者都不是。
raise "Inconsistency" if !!a ^ !!b
答案 5 :(得分:3)
这是"双阴",但这种做法令人沮丧。如果您正在使用rubocop,那么您会发现此类代码因Style/DoubleNegation
违规行为而抱怨。
由于这既是神秘的,也是多余的,应该避免 [然后解释:]将
!!something
更改为!something.nil?
答案 6 :(得分:0)
如果需要将枚举转换为布尔值,了解它的工作原理会非常有用。我使用classy_enum
gem:
class LinkStatus < ClassyEnum::Base
def !
return true
end
end
class LinkStatus::No < LinkStatus
end
class LinkStatus::Claimed < LinkStatus
def !
return false
end
end
class LinkStatus::Confirmed < LinkStatus
def !
return false
end
end
class LinkStatus::Denied < LinkStatus
end
然后在服务代码中我有,例如:
raise Application::Error unless !!object.link_status # => raises exception for "No" and "Denied" states.
实际上,bangbang运算符已经成为我称之为to_bool的方法。
答案 7 :(得分:0)
其他答案讨论了!!
的作用以及它是否是一种好的做法。
但是,所有答案都没有给出将值转换为布尔值的“标准Ruby方法”。
true & variable
TrueClass
是Ruby值true
的类,它实现了一种方法&
,它是documented,如下所示:
如果
false
是obj
或nil
,则返回false
,否则返回true
。
当您覆盖标准库时,为什么要使用肮脏的双重否定法?