Ruby中的双&符号

Cha*_*son 7 ruby

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

current_user = UserSession.find
id = current_user && current_user.record.id
Run Code Online (Sandbox Code Playgroud)

我不明白current_user && current_user.record.id如何返回当前用户ID.我认为这将返回一个布尔值.谁能解释一下这是如何工作的?

Jör*_*tag 19

BooleanRuby中没有类型; Ruby有一个相当简单的真理观(或者更确切地说,它有一个相当简单的虚假观点).

  • false对象,这是的一个实例,FalseClass被认为是falsy
  • nil对象,这是的一个实例,NilClassfalsy
  • 每个其他对象都是真实的(显然,包括true对象,这是单例实例TrueClass)

[顺便说一句:这意味着大量的被认为是对象的falsy在一些其他语言,实际上truthy在红宝石,如整数0,真正的价值0.0,所述空字符串,则空数组,空散列,字符'F']

因此,布尔运算符&&,||,and并且or 返回布尔值.相反,它们返回确定表达式结果的第一个对象.

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

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

 a && b
Run Code Online (Sandbox Code Playgroud)

truthy如果这两个 abtruthy,否则falsy.所以,如果a假的,那就完全无关紧要了b:无论如何,结果都是假的.所以,我们也可以简单地回归a.(记住,一个不必是false,它也可能是nil,程序员可能想知道它是哪一个.)

如果,OTOH,a真实的(IOW它既不是nil也不是false),那么整个表达的结果完全依赖于b:如果b真实的,整个结果将是真实的,否则如果b假的,整个结果将是假的.所以,我们也可以回归b自己,而不是先将其转换为布尔值.

||or类似于或者更准确地说&&and.

你发布了这个例子:

id = current_user && current_user.record.id
Run Code Online (Sandbox Code Playgroud)

在这里,作者甚至不希望 current_user成为布尔值!相反,他希望它可以是一个User或者一个nil.但这完全没问题,因为a User真实的并且nil假的,所以它们仍然可以用在布尔表达式中.

其基本意图是作者所要防止NoMethodError被提出例外,如果他试图调用#recordnil.

另一种表达方式是

id = current_user.record.id unless current_user.nil?
Run Code Online (Sandbox Code Playgroud)

如果您需要所有详细信息,请查看ISO Ruby规范草案的第11.1节(第36页)或RubySpec项目的可删除规范.(这是一个&&.)

为了好玩,我编写了Ruby的布尔运算符和条件表达式纯Ruby实现.实现的核心是这两个 混合.


Ry4*_*ase 9

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

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

if (current_user is TRUE) {
    id = current_user.record.id;
]
Run Code Online (Sandbox Code Playgroud)

这里有一些控制台输出显示如果第一个值为真,你得到第二个值:

irb(main):005:0> true && 9
=> 9
Run Code Online (Sandbox Code Playgroud)

如果第一个是零则为零:

irb(main):008:0> nil && 9
=> nil
Run Code Online (Sandbox Code Playgroud)

  • 真的,这与短路无关; 在Ruby,Perl和其他动态语言中,语言设计者选择`&&`来返回第一个false-ish值(或者最后一个值,如果所有都是true-ish),并且`||`返回第一个true- ish值(或最后一个值,如果所有都是假的).短路只意味着它在该返回点停止,但即使没有短路,返回值也是相同的. (4认同)