什么!在红宝石中意味着什么?


134

只是想知道!!Ruby中有什么。

Answers:


161

不是这样的。它用于将值转换为布尔值:

!!nil   #=> false
!!"abc" #=> true
!!false #=> false

尽管通常不需要使用,因为Ruby的唯一错误值是niland false,因此通常最好保持该约定。

认为是

!(!some_val)

合法使用的一件事是防止返回大量数据。例如,您可能不想在您的has_image?方法中返回3MB的图像数据,或者您可能不想在logged_in?方法中返回整个用户对象。使用!!将这些对象转换为简单的true/ false


8
使用它不是一个坏习惯。在谓词(以?结尾的方法)中经常使用Double bang返回明确的布尔值。
斯旺德

6
Alex,您真的不必担心返回大对象,因为Ruby会返回引用,而不是对象的副本。
DSimon

10
@DSimon,有时您确实需要担心大型对象,例如在调试过程中打印或记录值时。
韦恩·康拉德

为什么不返回.nil?而不是使用!!?有区别吗?
ashes999 2014年

3
当您的价值是booelan时,会有区别。!!true #=> truetrue.nil? #=> false
Alex Wayne

31

true如果右边的对象不是nil和不是falsefalse则返回,如果是nil或,则返回false

def logged_in?   
  !!@current_user
end

1
它来自Restful_Auth吗?:D
卡梅伦

14

!表示否定布尔状态,!除了双重否定外,2 没什么特别的。

!true == false
# => true

它通常用于强制方法返回布尔值。它将检测任何类型的真实性,例如字符串,整数和不包含的真实性,并将其转换为布尔值。

!"wtf"
# => false

!!"wtf"
# => true

一个更实际的用例:

def title
  "I return a string."
end

def title_exists?
  !!title
end

当您要确保返回布尔值时,这很有用。恕我直言,尽管看到两者if 'some string'并且if true是完全相同的流程,这是毫无意义的,但是有人发现显式返回布尔值很有用。


在我看来,这只是比使用if语句或三元运算符更快的方法。既然您不能只返回title,不妨做一些最接近的事情……我想
卡森·迈尔斯

6

请注意,该惯用语也存在于其他编程语言中。C没有内在bool类型,因此所有布尔值都int0或的规范值键入1。以以下示例为例(为清楚起见添加了括号):

!(1234) == 0
!(0) == 1
!(!(1234)) == 1

“ not-not”语法将任何非零整数转换1为规范的布尔true值。

但是,总的来说,我发现进行合理的比较比使用这种不常见的习惯要好得多:

int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious

或者只是(x)。!! 当您需要获得0/1时很有用。您可能会考虑(x)吗?1:0清除器。
derobert

3

如果您需要执行互斥或,则非常有用。从马特·范·霍恩(Matt Van Horn)的答案抄袭而来,并做了一些修改:

1 ^ true
TypeError: can't convert true into Integer

!!1 ^ !!true
=> false

我使用它来确保两个变量都为nil或都不为nil。

raise "Inconsistency" if !!a ^ !!b

3

这是“双重否定”,但不鼓励这样做。如果您使用的是rubocop,则会看到它在这样的代码上抱怨Style/DoubleNegation违规。

基本原理指出:

由于这既是隐秘的又通常是多余的,应避免使用[然后解释:]更改!!something!something.nil?


1
但是... !!false # => false虽然!false.nil? # => true
道格(Doug)

@Doug如果您知道您有一个布尔值,则它是多余的(只需使用该值)。如果不这样做,则可以使用!(foo.nil? || foo == false)-更详细,是,但隐秘性较低。
David Moles

0

如果需要将枚举转换为布尔值,则了解其工作原理可能会很有用。我有使用classy_enumgem 做到这一点的代码:

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的方法的东西。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.