红宝石是什么意思?

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

18627 次浏览

不是不是。

它用于将值转换为布尔值:

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

但是通常没有必要使用它,因为 Ruby 的唯一假值是 nilfalse,所以通常最好保留这个约定。

就当是

!(!some_val)

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

如果右边的对象不是 nil而不是 false,则返回 true; 如果是 nilfalse,则返回 false

def logged_in?
!!@current_user
end

注意,这个习惯用法也存在于其他编程语言中。C 没有固有的 bool类型,所以所有布尔值都被类型化为 int,标准值为 01。举这个例子(为了清楚起见,添加了括号) :

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

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

不过,总的来说,我认为,与使用这个不常见的成语相比,进行一个合理的比较要好得多:

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

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

!true == false
# => true

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

!"wtf"
# => false


!!"wtf"
# => true

一个更真实的用例:

def title
"I return a string."
end


def title_exists?
!!title
end

当您希望确保返回布尔值时,这非常有用。恕我直言,虽然看到 if 'some string'if true都是完全相同的流程,但是显式返回布尔值是有用的。

如果你需要做一个 独家或,这是很有用的。复制 Matt Van Horn 的答案,稍作修改:

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


!!1 ^ !!true
=> false

我使用它来确保两个变量要么都是 nil,要么都不是 nil。

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

如果需要将枚举转换为布尔值,理解它的工作原理会很有用。我的代码就是这么做的,使用 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.

实际上,bang bang 操作符已经变成了我本来可以写成的名为 to _ bool 的方法。

这是“双重否定”,但这种做法正受到阻碍。如果您正在使用 机械警察,您将看到它在这样的代码中抱怨 Style/DoubleNegation冲突。

合理性指出:

由于这样做既含糊不清,而且通常是多余的,因此应该避免这样做 把 !!something改成 !something.nil?

其他的答案讨论了 !!是做什么的,以及它是否是一个好的实践。

然而,没有一个答案给出将值转换为布尔值的“标准 Ruby 方法”。

true & variable

Ruby 值 true的类 TrueClass实现了一个方法 &,即 记录在案,如下所示:

如果 objnilfalse,则返回 false,否则返回 true

既然标准库已经覆盖了,为什么还要使用肮脏的双重否定呢?