我对 ruby 中的 OR EQUALS (
||=
) 运算符有一些疑问。 ruby解释器是如何实现的呢?这是代码示例:
class C
def arr
@num ||= []
end
end
在这种情况下,当我们使用 OR EQUALS 运算符时,第一次调用此方法会初始化变量并添加一个元素,这很好。当第二次调用
arr
时,它如何知道数组中有一个元素..
在 Ruby 中,有两个值被视为逻辑假。第一个是布尔值
false
,另一个是nil
。任何非nil
且不明确false
的事物都是true
。第一次使用该方法时,@num
是 nil
,它被视为 false
,并且需要评估 or
的逻辑 ||=
部分,并最终将空数组分配给 @num
。由于现在它是非nil
,因此它等同于true
。由于无论 true || x
是什么,x
都是 true,因此在将来的调用中,Ruby 会短路求值并且不执行赋值。
一般来说,
x ||= y
相当于x = x || y
,只是简写而已。它以扩展形式实现,与 &&=
、+=
或 -=
相同。
大多数编程语言(包括 Ruby)都会在遇到第一个
true值时停止执行逻辑比较语句(如
||
)并返回该值。同样,当使用 &&
时,它将在第一个 false值处停止。
一般而言:
假 || foo()
这将返回
false
并且不评估 foo()
。
该模式最好被描述为“惰性初始化程序”,即变量仅定义一次,但仅在实际使用时定义。这与“热切初始化程序”形成鲜明对比,后者会尽早执行此操作,就像在
initialize
方法中一样。
您会看到此模式的其他版本,例如:
def arr
@num ||= begin
stuff = [ ]
# ...
stuff
end
end
这可以处理初始值不那么微不足道并且可能需要一些工作才能生成的情况。再说一次,它仅在第一次调用该方法时才实际生成。
Ruby 如何知道在第二遍时不要再次初始化它?很简单,到那时
@num
已经被定义为某个东西了。
请注意,如果您使用像
false
这样的值,这些值将被评估为非 true,那么 ||=
每次都会触发。 Ruby 中唯一的两个逻辑错误值是 nil
和 false
,所以大多数时候这不是问题。
如果您还需要处理
false
,则必须以长格式执行此操作:
def arr
return @num unless num.nil?
@num = false
end
有人讨论添加一个类似
||=
的运算符,该运算符只会在 nil
上触发,但我认为这还没有添加到 Ruby 中。