在ruby && =运算符是片状?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在ruby && =运算符是片状?相关的知识,希望对你有一定的参考价值。

在Ruby中遇到了一种奇怪的行为。不知道这只是我。我在ruby 2.3.3上。这是日志。按顺序操作它们,你应该能够重现它。

[1] pry(main)> a &&= nil.a
=> nil
[2] pry(main)> a &&= 1.to_s
=> nil
[3] pry(main)> a = 1 && 1.to_s
=> "1"
[4] pry(main)> a &&= 1.to_s
=> "1"
[5] pry(main)> a &&= nil.a
NoMethodError: undefined method `a' for nil:NilClass
from (pry):5:in `__pry__'

看看1和[5],以及2和[4]

编辑:

有一个similar question on SO。还有一个试图解释它的blog post。但我不认为他们会解释它。

SO thread,它说&&=x = x && y if x的捷径。但考虑一下:

num = 1
a &&= num.to_s
# => nil

VS

num = 1
a = num && num.to_s if num
# => "1"

在红宝石如果a未定义,a = a给你nilx = x && y if x本身就是一个奇怪的操作。

x = x && y if x

这应该与下面相同

if x
  x = x && y
end

但这会引发错误,因为没有定义x。那么哪个部分首先被评估?是x = x && y还是if x

答案

关于&&=的属性,值得注意的是Stefan下面提到的一些事情:

  • 无论是否实际进行了分配,始终会考虑左侧的变量。
  • 如果没有显式赋值,则定义的变量假定nil的值。
  • 如果a在逻辑上是正确的,或者更具体地说,如果a不是nilfalse之一,则仅评估右侧的术语。
  • 因此,如果a在逻辑上不正确,那么右侧只需要在语法上有效,因为它不会被评估。这意味着像nil.a这样的破解代码在这些特定条件下是可以接受的,它将被解析但是否则会被忽略。
  • 如果anilfalse那么a的值不会改变。

a &&= b的长版本实际上是:

a = if (a)
  b
else
  a
end

b可以是任何表达,包括像a &&= b &&= c这样的东西

至于您的示例,这与表达式的右侧是否得到评估有关。在第一种情况下,a是未定义的,所以它不会。

后来当你真正将a定义为某个东西时,它必须执行右侧,所以你最终评估nil.a并且它会爆炸。

在这种情况下,您可以执行任何操作:

nil && whatever(this!, will!, not!, ever!, run!)

它不是片状的,它的表现就像你认为的那样。 &&是评估短路的东西之一。那是在:

a && b && c && d

实际解释是:

if a
  if b
    if c
      d
    end
  end
end

因此,在这种表示中,显而易见的是,如果任何这些条件失败,它就会退出并跳过其余条件。

需要注意的一点是a自动使用&&=存在:

local_variables
# => [:_]
a &&= true
# => nil
local_variables
# => [:a,:_]

&&不是这样。

以上是关于在ruby && =运算符是片状?的主要内容,如果未能解决你的问题,请参考以下文章

Ruby中And/&&的运算符优先级[重复]

& 是啥意思。 (& 点)在 Ruby 中是啥意思?

无法理解 ruby​​ 逻辑运算符的结果 [重复]

什么是 Ruby <=>(宇宙飞船)运算符?

红宝石连接和联合运算符[重复]

Ruby - Array#<< 和 Array#push 之间的区别