Here is my simple test code:
def test_function
0.tap do |v|
v += 10
end
end
p test_function
Why I get 0 here ? I was waiting to get 10.
Update:
class TestClass
def initialize
@v = 0
end
def inc
@v = @v + 1
end
end
def test_function
0.tap do |v|
v += 10
end
end
def test_function_2
TestClass.new.tap { |obj|
obj.inc
}
end
p test_function
p test_function_2
0
TestClass:0x29244f0 @v=1
The reason is that the original object is not changed by the += operator. So what happens it that you create a reference to it in the block, change the reference to point to an other object, which is larger by 10 and then return. the value of 0 stays the same.
And thing about it -- this is what you want to happen. The += operator does not change the object it operates on. It returns another different object and assigns the reference to it. This is like:
v = 0
v = v + 10
You wouldn't expect 0 == 10
to be true after this, right?
There is additional answer here: The method tap
returns the original object. You can use it e.g. for side-effects, like reporting, collecting stats or logging. It doesn't give you extra under-the-hood access to the original object.
v = [0,1,2]
v.tap { |array| array.map { |x| x + 1 } }
=> [0,1,2]
v.tap { |array| array.map! { |x| x + 1 } }
=> [1,2,3]
A variant of your test_function_2 could be used, where an object that you control has an Integer property, even just an array with one element:
def test_function
[0].tap do |v|
v[0] += 10
end
end
p test_function[0]
=> 10
. . . depends what you are trying to do?
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