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?
Ruby is pass-by-value, always. But in some cases this value is a pointer (which, I guess, some consider pass-by-reference).
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With