这是我的简单测试代码:
def test_function
0.tap do |v|
v += 10
end
end
p test_function
为什么我在这里得0?我等着10点。
更新
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
答案 0 :(得分:8)
原因是+ =运算符不会更改原始对象。那么在块中创建对它的引用会发生什么呢,将引用更改为指向另一个对象,该对象大于10然后返回。 0的值保持不变。
关于它的事情 - 这就是你想要发生的事情。 + =运算符不会更改其操作的对象。它返回另一个不同的对象并为其分配引用。这就像:
v = 0
v = v + 10
在此之后你不希望0 == 10
成立,对吗?
答案 1 :(得分:4)
此处还有其他答案:方法tap
返回原始对象。你可以使用它,例如用于副作用,如报告,收集统计数据或记录。它不会为您提供额外的原始对象的底层访问权限。
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]
可以使用test_function_2的变体,其中您控制的对象具有Integer属性,即使只是包含一个元素的数组:
def test_function
[0].tap do |v|
v[0] += 10
end
end
p test_function[0]
=> 10
。 。 。取决于你想要做什么?