Ruby'tamp'方法 - 内部分配

mde*_*tis 24 ruby

最近我发现tap可以用来"运用"为新变量赋值; 例如,用于创建和填充数组,如下所示:

array = [].tap { |ary| ary << 5 if something }
Run Code Online (Sandbox Code Playgroud)

此代码将推5array,如果something是truthy; 否则,array将保持空白.

但我不明白为什么执行这段代码后:

array = [].tap { |ary| ary += [5] if something }
Run Code Online (Sandbox Code Playgroud)

array仍然是空的.谁能帮我?

sep*_*p2k 41

在第一种情况下array,ary指向同一个对象.然后使用该<<方法改变该对象.现在改变了指向arrayary指向的对象.

在第二种情况下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方法,该方法也应该比使用更快+=.

  • ADD:`a + = b`的作用类似于'a = a + b` - 这里创建新对象的事实更为明显. (5认同)

bam*_*ery 22

我想稍微扩展一下:

array = [].tap { |ary| ary << 5 if something }
Run Code Online (Sandbox Code Playgroud)

这是做什么的(假设something是真的):

  1. 分配array[]一个空数组.

    array.object_id = 2152428060
    
    Run Code Online (Sandbox Code Playgroud)
  2. 传递[]到块ary.aryarray指向同一个数组对象.

    array.object_id = 2152428060
    ary.object_id = 2152428060
    
    Run Code Online (Sandbox Code Playgroud)
  3. 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)
  1. 相同
  2. 相同
  3. 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执行块.