Ruby布尔型的双重否定惯例

16

有人能告诉我为什么很多Ruby布尔方法使用这种双重否定的惯例吗?

!!(boolean expression)

不是 Ruby 程序员,但我想将值强制转换为布尔值? - Ethan
1
密切相关:https://dev59.com/nnRB5IYBdhLWcg3wv5tA - Andrew Grimm
3个回答

22

双重否定确保无论初始值是什么,您始终会得到truefalse,而不是一些神秘的值。

这很方便,因为它避免了对您不再需要的对象进行悬空引用,或者需要区分两种假值nilfalse

通常您会看到像这样编写的方法:

def logged_in?
  !!@session_user
end

这将返回truefalse的值,该值可以用于所需的任何目的。与此相比:

def logged_in?
  @session_user
end
在这种情况下,如果你保存这个值,实际上是在保存整个@session_user对象,这可能占用相当大的内存空间。这种内存直到你对它的引用超出作用域后才能释放。由于只有一个true和一个false,因此不需要进行垃圾回收。

3
假设您想定义一个返回布尔值的方法。例如,判断字符串是否与正则表达式匹配。
class String
  def include? regex; self =~ regex end
end

如果您执行以上操作,则当不匹配时它将返回nil,并在匹配时返回整数。在许多情况下,这并不太重要(nil类似于false,而true可以替代整数)。但是,如果您真的想要布尔值作为返回值,那么可以执行以下操作。
class String
  def include? regex; !!(self =~ regex) end
end

当匹配时会返回true,不匹配则返回false


1

在我看来,Ruby 在布尔值方面有点过于聪明了。这是解决聪明导致问题的情况的一种方法。

以下是过度聪明的部分:没有布尔类。相反,有一个约定,任何值都可以作为布尔值。在需要真或假值的上下文中,nilfalse 表示“false”,而其他任何值表示“true”。truefalse 的值不是特殊类的一部分,它们是各自类的唯一成员 - 它们存在只是为了使代码更易读。

我想这在大多数情况下都很好用,但是偶尔你需要一个始终为 truefalse 的布尔值。例如,最近我需要比较两个布尔值,并在它们不同时执行某些特殊操作;唯一的问题是,其中一个是 truefalse,而另一个是 1 或 nil。解决方法?利用 !!nil == false!!1 == true 这个事实。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接