最近我发现可以使用tap
来“彻底”为新变量赋值;例如,用于创建和填充数组,如下所示:
array = [].tap { |ary| ary << 5 if something }
如果5
真实,此代码会将array
推送到something
;否则,array
将保持为空。
但是我不明白为什么在执行这段代码之后:
array = [].tap { |ary| ary += [5] if something }
array
仍为空。任何人都可以帮助我吗?
答案 0 :(得分:40)
在第一种情况下,array
和ary
指向同一个对象。然后使用<<
方法改变该对象。 array
和ary
指向的对象现在已更改。
在第二种情况下,array
和ary
再次指向同一个数组。您现在重新分配ary
变量,以便ary
现在指向一个新数组。但是,重新分配ary
对array
没有影响。在ruby中重新分配变量永远不会影响其他变量,即使它们在重新分配之前指向同一个对象。
换句话说,array
仍为空,原因与x
在以下示例中不会为42的原因相同:
x = 23
y = x
y = 42 # Changes y, but not x
编辑:要将一个数组附加到另一个数组,您可以使用concat
方法,该方法也应该比使用+=
更快。
答案 1 :(得分:21)
我想稍微扩展一下:
array = [].tap { |ary| ary << 5 if something }
这是做什么的(假设something
是真的):
将array
分配给[]
,这是一个空数组。
array.object_id = 2152428060
将[]
作为ary
传递给该块。 ary
和array
指向同一个数组对象。
array.object_id = 2152428060
ary.object_id = 2152428060
ary << 5
&lt;&lt;是一种变异方法,意味着它将修改接收对象。它类似于将!
附加到方法调用的惯用语,意思是“在适当的位置修改它!”,就像在.map
vs .map!
中一样(虽然爆炸没有任何内在意义)在方法名称中自己)。已插入ary
,因此ary
= array
= [5]
array.object_id = 2152428060
ary.object_id = 2152428060
我们以array
等于[5]
在第二个例子中:
array = [].tap{ |ary| ary += [5] if something }
ary += 5
+=
是ary = ary + 5
的缩写,因此首先修改(+
),然后分配(=
),订购。它给出了修改对象的外观,但实际上并没有。它创造了一个全新的对象。
array.object_id = 2152428060
ary.object_id = 2152322420
所以我们以array
作为原始对象,一个包含object_id=2152428060
的空数组和ary
,一个包含5个object_id = 2152322420
的项目的数组结束。在此之后ary
没有任何事情发生。它与array
的原始分配无关,已经发生过。在分配array
后,点击执行该块。