关于" || ="的怀疑红宝石中的OR EQUALS运算符

时间:2014-06-16 21:06:13

标签: ruby operators equals core

我对ruby中的OR EQUALS(||=)运算符有些怀疑。 ruby解释器如何实现它?以下是代码示例:

class C
  def arr
    @num ||= []
  end
end

当我们在这种情况下使用OR EQUALS运算符时,第一次调用此方法会初始化变量并添加一个元素,这很好。当第二次调用arr时,它如何知道该数组中有一个元素..

2 个答案:

答案 0 :(得分:3)

在Ruby中,有两个值被视为逻辑错误。第一个是布尔值false,另一个是nil。任何非nil且未明确false的内容都是true。第一次通过该方法,@numnil,被视为falseor的{​​{1}}部分需要进行评估并最终结束将空数组分配给||=。由于现在不是@num,它等同于nil。由于true无论true || x是什么都是正确的,因此在将来的调用中,Ruby会使评估短路并且不会进行分配。

答案 1 :(得分:0)

一般来说,x ||= y相当于x = x || y,它只是简写。它是作为展开式表单实现的,与&&=+=-=相同。

包含Ruby的大多数编程语言将停止在遇到的第一个 true 值上执行像||这样的逻辑比较语句并返回该语句。同样,使用&&时,它将停止在第一个 false 值。

一般而言:

false || FOO()

这将返回false而不是评估foo()

该模式最好被描述为“延迟初始化器”,即变量仅定义一次,但仅在实际使用时定义。这与“渴望初始化程序”形成对比,“初始化程序”会尽可能早地完成,例如initialize方法内部。

您将看到此模式的其他版本,例如:

def arr
  @num ||= begin
    stuff = [ ]
    # ...
    stuff
  end
end

这可以处理初始值不是很简单并且可能需要一些工作来生成的情况。再一次,它只是在第一次调用方法时才生成。

Ruby如何知道第二遍不再初始化它?很简单,到那时@num已被定义为某种东西。

请注意,如果您使用的false值会被评估为非真值,那么每次都会触发||=。 Ruby中唯一两个逻辑错误的值是nilfalse,因此大多数情况下这不是问题。

如果您还需要处理false,则必须以长篇方式执行此操作:

def arr
  return @num unless num.nil?

  @num = false
end

有人提到添加||= - 类似的运算符只能在nil上触发,但我认为它还没有被添加到Ruby中。