最近我发现tap可以用来"运用"为新变量赋值; 例如,用于创建和填充数组,如下所示:
array = [].tap { |ary| ary << 5 if something }
Run Code Online (Sandbox Code Playgroud)
此代码将推5入array,如果something是truthy; 否则,array将保持空白.
但我不明白为什么执行这段代码后:
array = [].tap { |ary| ary += [5] if something }
Run Code Online (Sandbox Code Playgroud)
array仍然是空的.谁能帮我?
sep*_*p2k 41
在第一种情况下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
Run Code Online (Sandbox Code Playgroud)
编辑:要将一个数组附加到另一个数组,您可以使用该concat方法,该方法也应该比使用更快+=.
bam*_*ery 22
我想稍微扩展一下:
array = [].tap { |ary| ary << 5 if something }
Run Code Online (Sandbox Code Playgroud)
这是做什么的(假设something是真的):
分配array给[]一个空数组.
array.object_id = 2152428060
Run Code Online (Sandbox Code Playgroud)传递[]到块ary.ary并array指向同一个数组对象.
array.object_id = 2152428060
ary.object_id = 2152428060
Run Code Online (Sandbox Code Playgroud)ary << 5 <<是一种变异方法,意味着它将修改接收对象.它类似于附加!到方法调用的习语,意思是"在适当的位置修改它!",就像在.mapvs中一样.map!(尽管bang在方法名称中没有任何内在含义).ary已插入5,所以ary= array=[5]
array.object_id = 2152428060
ary.object_id = 2152428060
Run Code Online (Sandbox Code Playgroud)我们以array平等而告终[5]
在第二个例子中:
array = [].tap{ |ary| ary += [5] if something }
Run Code Online (Sandbox Code Playgroud)
ary += 5 +=是的缩写ary = ary + 5,所以它是第一个修改(+),然后是赋值(=),按顺序.它给出了修改对象的外观,但实际上并没有.它创造了一个全新的对象.
array.object_id = 2152428060
ary.object_id = 2152322420
Run Code Online (Sandbox Code Playgroud)因此,我们最终与array作为原始对象,具有一个空数组object_id=2152428060,并且ary,用含有5带有一个项目的阵列object_id = 2152322420.ary在此之后没有任何事情发生.它不涉及array已经发生的原始任务.array分配后,Tap执行块.