Question

So apparently it seems that ruby is a pass-by reference language:

$ 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]

I.e., both the constructed array and the block seem to deal with references to the original class instance variable objects.

However, these references seem to create copies as soon as I try to write into them:

>> [@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

I had a handful of class instance variable objects that I needed to transform via a function so I thought I'd save keystrokes by making use of the pass-by-reference thing and do something like:

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

but it doesn't seem to work due to this copy-on-write thing that seems to be going on.

Is there a way to turn it off? How would you accomplish my while keeping the code both DRY and efficient at the same time?

Was it helpful?

Solution 2

Is this what you are looking for ?

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

OTHER TIPS

Ruby is pass-by-value, always. But in some cases this value is a pointer (which, I guess, some consider pass-by-reference).

Edit:

Building on Arup's answer, here's a version that processes only some ivars.

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

Ruby is pass-by-value only. There is no pass-by-reference in Ruby. Every value in Ruby is a reference (a pointer to an object). So @foo is a pointer to an object, @bar is a pointer to an object, @foo.object_id is a pointer to an object, etc. "Objects" are not values in Ruby. All values in Ruby are passed or assigned by value.

In the first piece of code, you are accessing methods of the object pointed to by each reference. If you pass or assign the reference, you will have a new copy of the reference, but of course it points to the same object as the original reference.

In the second piece of code, you are assigning to the local copy of the reference to make it point to something else. This of course does not change what object the reference in the original scope pointed to.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top