Ruby'tamp'方法 - 内部分配

时间:2011-01-27 16:47:39

标签: ruby

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

array = [].tap { |ary| ary << 5 if something }

如果5真实,此代码会将array推送到something;否则,array将保持为空。

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

array = [].tap { |ary| ary += [5] if something }

array仍为空。任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:40)

在第一种情况下,arrayary指向同一个对象。然后使用<<方法改变该对象。 arrayary指向的对象现在已更改。

在第二种情况下,arrayary再次指向同一个数组。您现在重新分配ary变量,以便ary现在指向一个新数组。但是,重新分配aryarray没有影响。在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是真的):

  1. array分配给[],这是一个空数组。

    array.object_id = 2152428060
    
  2. []作为ary传递给该块。 aryarray指向同一个数组对象。

    array.object_id = 2152428060
    ary.object_id = 2152428060
    
  3. ary << 5&lt;&lt;是一种变异方法,意味着它将修改接收对象。它类似于将!附加到方法调用的惯用语,意思是“在适当的位置修改它!”,就像在.map vs .map!中一样(虽然爆炸没有任何内在意义)在方法名称中自己)。已插入ary,因此ary = array = [5]

    array.object_id = 2152428060
    ary.object_id = 2152428060
    
  4. 我们以array等于[5]

    结束

    在第二个例子中:

    array = [].tap{ |ary| ary += [5] if something }    
    
    1. 相同
    2. 相同
    3. ary += 5 +=ary = ary + 5的缩写,因此首先修改(+),然后分配(=),订购。它给出了修改对象的外观,但实际上并没有。它创造了一个全新的对象。

      array.object_id = 2152428060
      ary.object_id = 2152322420
      
    4. 所以我们以array作为原始对象,一个包含object_id=2152428060的空数组和ary,一个包含5个object_id = 2152322420的项目的数组结束。在此之后ary没有任何事情发生。它与array的原始分配无关,已经发生过。在分配array后,点击执行该块。