下面的代码在Ruby中是什么意思?
||=
它的语法有什么意义或原因吗?
下面的代码在Ruby中是什么意思?
||=
它的语法有什么意义或原因吗?
当前回答
a ||= b
等于
a || a = b
而不是
a = a || b
因为您使用默认值定义哈希(对于任何未定义的键,哈希将返回默认值)
a = Hash.new(true) #Which is: {}
如果你使用:
a[10] ||= 10 #same as a[10] || a[10] = 10
A仍然是:
{}
但如果你这样写
a[10] = a[10] || 10
一个变成了:
{10 => true}
因为你已经在键10处赋值了它自己的值,默认为true,所以现在哈希是为键10定义的,而不是一开始就不执行赋值。
其他回答
x ||= y
is
x || x = y
"如果x为假或未定义,则x指向y"
一个常见的误解是,||= b并不等同于a = a || b,但它的行为就像|| a = b。
但这里有一个棘手的情况。如果a未定义,则|| a = 42将引发NameError,而||= 42将返回42。所以,它们似乎不是等价的表达式。
这个问题在Ruby邮件列表和Ruby博客上讨论得如此频繁,以至于现在Ruby邮件列表上甚至有一些线程,它们的唯一目的就是收集到Ruby邮件列表上讨论这个问题的所有其他线程的链接。
这里有一个:||= (OR Equal)线程和页面的最终列表
如果你真的想知道发生了什么,可以看看Ruby语言规范草案的第11.4.2.3节“缩写赋值”。
作为第一近似,
a ||= b
等于
a || a = b
并不等同于
a = a || b
然而,这只是一种近似,特别是在a未定义的情况下。根据是简单的变量赋值、方法赋值还是索引赋值,语义也有所不同:
a ||= b
a.c ||= b
a[c] ||= b
都有不同的待遇。
||=称为条件赋值运算符。
它基本上像=一样工作,但如果一个变量已经被赋值,它将什么都不做。
第一个例子:
x ||= 10
第二个例子:
x = 20
x ||= 10
在第一个例子中,x现在等于10。然而,在第二个例子中,x已经被定义为20。所以条件运算符没有作用。执行X ||= 10后,X仍然是20。
A ||= b和A = b是一样的如果A。nil?或者a = b,除非a
但是所有3个选项都能显示相同的性能吗?在Ruby 2.5.1中
1000000.times do
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
end
在我的电脑上花费0.099秒,而
1000000.times do
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
end
用时0.062秒。这几乎快了40%。
然后我们还有:
1000000.times do
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
end
这需要0.166秒。
并不是说这将在一般情况下产生重大的性能影响,但是如果您确实需要最后一点优化,那么可以考虑这个结果。 顺便说一下:a = 1,除非a对新手来说更容易理解,否则它是不言自明的。
注1:重复分配行多次的原因是为了减少循环在测量时间上的开销。
注2:如果我在每次赋值前执行a=nil,结果是类似的。