通过splat运算符引用块来传递参数

当使用splat运算符通过引用将参数传递给块时,似乎会复制参数。

我有这个:

def method a = [1,2,3] yield(*a) pa end method {|x,y,z| z = 0} #=> this puts and returns [1, 2, 3] (didn't modified the third argument) 

我如何通过引用传递这些参数? 如果我直接传递数组似乎有效,但splat运算符在这里更实用,直观和可维护。

  1. 在Ruby中,当你写x = value你正在创建一个新的局部变量x无论它是否先前存在(如果它存在,名称只是反弹而原始值保持不变)。 因此,您无法以这种方式就地更改变量。

  2. 整数是不可变的。 因此,如果您发送一个整数,则无法更改其值。 请注意,您可以更改可变对象(字符串,哈希,数组……):

     def method a = [1, 2, "hello"] yield(*a) pa end method { |x,y,z| z[1] = 'u' } # [1, 2, "hullo"] 

注意:我试图回答你的问题,现在我的观点是:更新方法或块中的参数会导致错误的代码(你再也没有参考透明度了)。 返回新值并让调用者更新变量本身(如果有的话)。

这里的问题是=符号。 它使局部变量z被分配给另一个对象。

以字符串为例:

 def method a = ['a', 'b', 'c'] yield(*a) pa end method { |x,y,z| z.upcase! } # => ["a", "b", "C"] 

这清楚地表明z与数组的第三个对象相同。

这里的另一点是你的例子是数字。 Fixnums有固定的ID; 因此,您无法在保持相同的对象ID时更改数字。 要更改Fixnums,您必须使用=为变量分配一个新数字,而不是像inc!这样的自我更改方法inc! (此类方法不能存在于Fixnums上)。

是…数组包含对象的链接 。 在使用yield(*a)的代码中,然后在块中使用指向数组中对象的变量。 现在寻找代码示例:

 daz@daz-pc:~/projects/experiments$ irb irb(main):001:0> a = 1 => 1 irb(main):002:0> a.object_id => 3 irb(main):003:0> a = 2 => 2 irb(main):004:0> a.object_id => 5 

因此,在块中您不更改旧对象,您只需创建另一个对象并将其设置为变量 。 但是数组包含指向旧对象的链接。

看看调试内容:

 def m a = [1, 2] pa[0].object_id yield(*a) pa[0].object_id end m { |a, b| p a.object_id; a = 0; p a.object_id } 

输出:

 3 3 1 3 

我如何通过引用传递这些参数?

你不能在Ruby中通过引用传递参数。 Ruby是按值传递的。 总是。 没有例外,没有ifs,没有buts。

如果我直接传递数组似乎有效

我非常怀疑。 你根本无法通过Ruby中的引用传递参数。 期。