ruby中的变量引用

时间:2013-11-21 19:22:41

标签: ruby reference pass-by-reference copy-on-write

显然,ruby似乎是一种传递参考语言:

$ irb --simple-prompt 
>> @foo=1
=> 1
>> @bar=2
=> 2
>> @foo.object_id
=> 3
>> @bar.object_id
=> 5
>> [@foo,@bar].each {|e| puts e.object_id }
3
5
=> [1, 2]

即,构造的数组和块似乎都处理对原始类实例变量对象的引用。

但是,一旦我尝试写入这些引用似乎就会创建副本:

>> [@foo,@bar].each {|e| puts e+=1 }
2
3
=> [1, 2]
>> @foo
=> 1
>> @bar
=> 2
>> [@foo,@bar].map! {|e| e+1 }
=> [2, 3]
>> @foo
=> 1
>> @bar
=> 2

我有一些类实例变量对象,我需要通过函数进行转换,所以我想我会通过使用传递引用的东西来保存击键,并执行以下操作:

[@var1, @var2, @var3].map! {|v| my_function(v) }

但由于这种写入时的复制似乎正在发生,它似乎不起作用。

有没有办法把它关掉? 您如何在保持代码同时干燥和高效的同时完成我的工作?

3 个答案:

答案 0 :(得分:3)

Ruby始终是值传递。但在某些情况下,这个值是一个指针(我猜,有些人会考虑传递引用)。

编辑:

根据Arup的回答,这里是一个只处理一些ivars的版本。

[:@foo, :@bar].each do |var| 
  instance_variable_set(var, myfunction(instance_variable_get(var)))
end

答案 1 :(得分:2)

这是你在找什么?

@foo = 1
@bar = 2
instance_variables.each do |var| 
  instance_variable_set(var,instance_variable_get(var)+1)
end
@foo # => 2
@bar # => 3

答案 2 :(得分:0)

Ruby仅按值传递。 Ruby中没有pass-by-reference。 Ruby中的每个值都是引用(指向对象的指针)。所以@foo是指向对象的指针,@bar是指向对象的指针,@foo.object_id是指向对象的指针,等等。“对象”不是Ruby中的值。 Ruby中的所有值都是按值传递或分配的。

在第一段代码中,您正在访问每个引用所指向的对象的方法。如果您传递或指定引用,您将获得引用的新副本,但当然它指向与原始引用相同的对象。

在第二段代码中,您将分配引用的本地副本以使其指向其他内容。这当然不会改变原始范围中的引用所指向的对象。