使用splat运算符通过引用将参数传递给块时,参数似乎被复制了。
我有这个:
def method
a = [1,2,3]
yield(*a)
p a
end
method {|x,y,z| z = 0}
#=> this puts and returns [1, 2, 3] (didn't modified the third argument)
如何通过引用传递这些论点?如果我直接传递数组,它似乎可以工作,但splat操作符在这里会更加实用、直观和可维护。
-
在Ruby中,当您编写
x = value
时,您正在创建一个新的局部变量x
,无论它以前是否存在(如果它存在,则名称只是回弹,原始值保持不变)。因此,您将无法以这种方式在适当的位置更改变量。 -
整数是不可变的。所以,如果你发送一个整数,你就无法改变它的值。请注意,您可以更改可变对象(字符串、散列、数组等):
def method a = [1, 2, "hello"] yield(*a) p a end method { |x,y,z| z[1] = 'u' } # [1, 2, "hullo"]
注意:我已经试着回答了你的问题,现在我的观点是:更新方法或块中的参数会导致错误代码(你不再有引用透明度了)。如果愿意,返回新值并让调用者更新变量本身。
这里的问题是=
符号。它使局部变量z
被分配给另一个对象。
以字符串为例:
def method
a = ['a', 'b', 'c']
yield(*a)
p a
end
method { |x,y,z| z.upcase! } # => ["a", "b", "C"]
这清楚地表明z
与阵列的第三个对象相同。
这里的另一点是你的例子是数字。Fixnums有固定的id;因此,您不能在保持相同对象id的情况下更改数字。要更改Fixnums,必须使用=
为变量分配一个新数字,而不是像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]
p a[0].object_id
yield(*a)
p a[0].object_id
end
m { |a, b| p a.object_id; a = 0; p a.object_id }
输出:
3
3
1
3
如何通过引用传递这些论点?
Ruby中不能通过引用传递参数。Ruby是按值传递的。总是没有例外,没有如果,没有但是。
如果我直接通过阵列,它似乎可以工作
我对此深表怀疑。在Ruby中,您根本无法通过引用传递参数。时期