Ruby中的双&符号

时间:2010-01-01 05:30:58

标签: ruby

我正在使用Ruby on Rails的authlogic gem,我一直在使用以下内容来获取当前登录用户的id:

current_user = UserSession.find
id = current_user && current_user.record.id

我不明白current_user&& current_user.record.id返回当前用户ID。我认为这将返回一个布尔值。有人可以解释这是如何工作的吗?

2 个答案:

答案 0 :(得分:19)

Ruby中没有Boolean类型; Ruby对事实有一个相当简单的看法(或者更确切地说,它有一个相当简单的 falsehood 视图)。

  • false对象,FalseClass的单例实例被视为 falsy
  • nil对象,NilClass的单例实例 falsy
  • 每个其他对象 真实(显然包括true对象,它是TrueClass的单例实例

[BTW:这意味着很多在其他语言中被认为是 falsy 的对象在Ruby中实际上是 truthy ,就像整数0 ,实数值0.0,空字符串,空数组,空哈希,字符'F']

因此,布尔运算符&&||andor 不会返回布尔值。相反,他们返回确定表达式结果的第一个对象

(它们也是短路的,这意味着它们只评估确定表达式结果所需的最小子表达式。因此,另一种表述是它们返回最后一个表达式的结果反过来,这类似于块,方法,类主体和模块体所做的事情。)

那么,意味着返回确定结果的第一个对象是什么意思?这很简单,真的:表达式的结果

 a && b
如果 ab 真实

真实,否则虚假< / strong>即可。因此,如果a falsy 完全b无关:结果将是 falsy 办法。所以,我们也可以简单地返回a。 (请记住,a不必是false,也可能是nil,程序员可能想知道它是哪一个。)

如果,OTOH,a 真实(IOW既不是nil也不是false),那么整个表达式的结果是依赖于b:如果b 真实,则整个结果将为 truthy ,否则如果b falsy ,整个结果将是 falsy 。因此,我们也可以返回b本身,而不是先将其转换为布尔值。

||or&&and类似或更准确地

您发布了此示例:

id = current_user && current_user.record.id

在这里,作者甚至不希望 current_user成为布尔值!相反,他希望它可以是Usernil。但这非常好,因为User 真实nil 虚假,因此它们仍可用于布尔表达式。

基本意图是,如果作者试图在NoMethodError上致电#record,则希望阻止引发nil例外。

另一种表达方式是

id = current_user.record.id unless current_user.nil?

如果您需要所有血腥细节,请查看Draft ISO Ruby Specification的第11.1节(第36页)或RubySpec project的可删除规范。 (Here's the one for &&。)

为了好玩,我写了一次pure Ruby implementation of Ruby's Boolean operators and conditional expressions。这些实现的核心是two mixins

答案 1 :(得分:9)

逻辑和短路。这意味着如果构造是X&amp;&amp; Y和X是假的,然后Y永远不会被检查,因为整个事情肯定会产生错误。

该代码基本上是这样说的:

if (current_user is TRUE) {
    id = current_user.record.id;
]

这是一些控制台输出,显示如果第一个值为真,则获得第二个值:

irb(main):005:0> true && 9
=> 9

如果第一个是零则为零:

irb(main):008:0> nil && 9
=> nil