下面的代码在Ruby中是什么意思?

||=

它的语法有什么意义或原因吗?


当前回答

准确地说,||= b意味着“如果a是未定义的或假的(false或nil),将a设置为b并求值为(即返回)b,否则求值为a”。

其他人经常试图用||= b等价于|| a = b或a = a || b来说明这一点。这些等价有助于理解这个概念,但要注意,它们并非在所有条件下都是准确的。请允许我解释:

a ||= b ⇔ a || a = b? The behavior of these statements differs when a is an undefined local variable. In that case, a ||= b will set a to b (and evaluate to b), whereas a || a = b will raise NameError: undefined local variable or method 'a' for main:Object. a ||= b ⇔ a = a || b? The equivalency of these statements are often assumed, since a similar equivalence is true for other abbreviated assignment operators (i.e. +=,-=,*=,/=,%=,**=,&=,|=,^=,<<=, and >>=). However, for ||= the behavior of these statements may differ when a= is a method on an object and a is truthy. In that case, a ||= b will do nothing (other than evaluate to a), whereas a = a || b will call a=(a) on a's receiver. As others have pointed out, this can make a difference when calling a=a has side effects, such as adding keys to a hash. a ||= b ⇔ a = b unless a?? The behavior of these statements differs only in what they evaluate to when a is truthy. In that case, a = b unless a will evaluate to nil (though a will still not be set, as expected), whereas a ||= b will evaluate to a. a ||= b ⇔ defined?(a) ? (a || a = b) : (a = b)???? Still no. These statements can differ when a method_missing method exists which returns a truthy value for a. In this case, a ||= b will evaluate to whatever method_missing returns, and not attempt to set a, whereas defined?(a) ? (a || a = b) : (a = b) will set a to b and evaluate to b.

好的,好的,那么||= b等于什么?有办法在Ruby中表达这一点吗?

好吧,假设我没有忽略任何东西,我相信||= b在功能上等价于……(击鼓声)

begin
  a = nil if false
  a || a = b
end

坚持住!这不是第一个前面有noop的例子吗?嗯,不完全是。还记得我之前说的||= b只有当a是一个未定义的局部变量时,||= b才不等于|| a = b吗?如果为false,则a = nil确保a永远没有定义,即使这一行永远不会执行。Ruby中的局部变量是词法范围的。

其他回答

这就像延迟实例化。 如果变量已经定义,它将获取该值,而不是重新创建该值。

除非x X = y 结束

除非x有值(不是nil或false),否则将其设为y

等于

X ||= y

||= b是一个条件赋值运算符。它的意思是:

如果a是未定义的或假的,则计算b并将a设置为结果。 否则(如果定义了a并计算为真),则不计算b,并且不进行赋值。

例如:

a ||= nil # => nil
a ||= 0 # => 0
a ||= 2 # => 0

foo = false # => false
foo ||= true # => true
foo ||= false # => true

令人困惑的是,它看起来类似于其他赋值操作符(例如+=),但行为不同。

A += b转换为A = A + b ||= b大致可以转换为|| A = b

它是|| a = b的近似缩写。不同之处在于,当a未定义时,|| a = b将引发NameError,而||= b将a设置为b。如果a和b都是局部变量,这种区别不重要,但如果其中一个是类的getter/setter方法,则很重要。

进一步阅读:

http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html

irb(main):001:0> a = 1
=> 1
irb(main):002:0> a ||= 2
=> 1

因为a已经被设为1了

irb(main):003:0> a = nil
=> nil
irb(main):004:0> a ||= 2
=> 2

因为a是nil

b = 5
a ||= b

这句话的意思是:

a = a || b

这将是

a = nil || 5

所以最后

a = 5

现在如果你再调用这个:

a ||= b
a = a || b
a = 5 || 5
a = 5

b = 6

现在如果你再调用这个:

a ||= b
a = a || b
a = 5 || 6
a = 5 

如果你观察,b的值不会被分配给a, a仍然有5。

它是Ruby中用来加快访问速度的一种记忆模式。

def users
  @users ||= User.all
end

这句话的意思是:

@users = @users || User.all

第一次调用这个方法时,你会调用数据库。

以后对该方法的调用将只返回@users实例变量的值。