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

Edm*_*Lee 0 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__'
Run Code Online (Sandbox Code Playgroud)

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

编辑:

在SO上有一个类似的问题.还有一篇试图解释它的博客文章.但我不认为他们会解释它.

SO线程中,它表示&&=是一个快捷方式x = x && y if x.但考虑一下:

num = 1
a &&= num.to_s
# => nil
Run Code Online (Sandbox Code Playgroud)

VS

num = 1
a = num && num.to_s if num
# => "1"
Run Code Online (Sandbox Code Playgroud)

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

x = x && y if x
Run Code Online (Sandbox Code Playgroud)

这应该与下面相同

if x
  x = x && y
end
Run Code Online (Sandbox Code Playgroud)

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

tad*_*man 8

值得注意的是Stefan下面提到的几个关于以下属性的东西&&=:

  • 在左手侧的可变始终被认为是定义一个分配与否实际上是由.
  • nil如果没有显式赋值,则定义的变量采用值.
  • 右侧的术语仅在a逻辑上为真,或者更具体地,如果a不是nil或者中的一个时进行评估false.
  • 因此,如果a逻辑上不正确,那么右侧只需要在语法上有效,因为它不会被评估.这意味着破坏的代码nil.a在这些特定条件下是可以接受的,它将被解析,否则将被忽略.
  • 如果anil,false那么值a不会改变.

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

a = if (a)
  b
else
  a
end
Run Code Online (Sandbox Code Playgroud)

哪里b可以是任何表达,包括像a &&= b &&= c

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

稍后,当您实际定义a为某些东西时,它必须执行右侧,因此您最终会进行评估nil.a并且会爆炸.

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

nil && whatever(this!, will!, not!, ever!, run!)
Run Code Online (Sandbox Code Playgroud)

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

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

实际解释是:

if a
  if b
    if c
      d
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

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

要注意的一件事是a使用&&=自动弹出存在:

local_variables
# => [:_]
a &&= true
# => nil
local_variables
# => [:a,:_]
Run Code Online (Sandbox Code Playgroud)

这不是真的&&.